Call External C Library

Discussion forum for C++ and script developers who are using the QCAD development platform or who are looking to contribute to QCAD (translations, documentation, etc).

Moderator: andrew

Forum rules

Always indicate your operating system and QCAD version.

Attach drawing files, scripts and screenshots.

Post one question per topic.

Post Reply
zak
Junior Member
Posts: 11
Joined: Mon Apr 29, 2013 10:51 pm

Call External C Library

Post by zak » Tue Apr 30, 2013 4:38 pm

Is it possible to call an external c library from within the EMCA script environment? Or are scripts executed in a "sandbox" that not allow that, and would I instead have to modify C++ source (getting the applicable license of course) accomplish that kind of functionality?

Thanks, Zak

User avatar
andrew
Site Admin
Posts: 9019
Joined: Fri Mar 30, 2007 6:07 am

Re: Call External C Library

Post by andrew » Wed May 01, 2013 8:03 am

C/C++ code can only be called from ECMAScript if script wrappers exist (which is the case for most of the Qt and QCAD API).

You may provide script wrappers for any third-party library through a QCAD C++ plugin. A plugin implements a plugin interface which provides two functions:

Code: Select all

void init()
void initScriptExtensions(QScriptEngine& engine)
init() is called when the plugin is loaded. initScriptExtensions(QScriptEngine& engine) is called whenever a new script engine is created (one for the application, one for each new document).

Inside initScriptExtensions(QScriptEngine& engine), you can initialize any script wrappers. Script wrappers can make almost anything scriptable (C++ classes, C methods, enums, ...).

See also http://qt-project.org/doc/qt-4.8/scripting.html

zak
Junior Member
Posts: 11
Joined: Mon Apr 29, 2013 10:51 pm

Re: Call External C Library

Post by zak » Wed May 01, 2013 5:48 pm

Excellent! Your're using QT Script Engine, that makes sense. Thanks for the quick response.

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Call External C Library

Post by matthiaswm » Wed May 15, 2013 7:12 pm

Hmm. That is not entirely clear to me.

So I need to create a dynamic library with the "C" functions mentioned above, containing a Q... class interface. That much is clear.

But where do I put the library so that QCAD will find it in the initialization phase?
Or do I need to call something in the .js file to register my extension?
Or will I need another license?

I would use this to write a driver for my Laser Cutter. I want QCAD to communicate via USB with the cutter and upload and cut files right out of the software.

Thanks,

Matthias

User avatar
andrew
Site Admin
Posts: 9019
Joined: Fri Mar 30, 2007 6:07 am

Re: Call External C Library

Post by andrew » Wed May 15, 2013 8:05 pm

Typically, you would implement your C / C++ functions and classes in the plugin and expose a part of that functionality to ECMAScript.

The C++ classes are compiled into a library, together with a C++ class that implements the plugin interface (RPluginInterface). The compiled library is placed into the 'plugins' folder of the QCAD installation. Plugins are found and loaded automatically. A list of all loaded plugins can be found in the about dialog, plugins tab.

A 'Hello World' type example plugin implementation is available in support/exampleplugin:
https://github.com/qcad/qcad/tree/maste ... mpleplugin

For your use case, you might have a C++ class UsbUploader with a function uploadFile(const QString& fileName).
After making that class and function scriptable, you can create an ECMAScript that calls the C++ member function as follows:

Code: Select all

var uploader = new UsbUploader([some parameters...]);
uploader.uploadFile("/path/to/file.cnc");
Please keep in mind that all this information relates to the latest code available in the Git repository. Nothing is cast in stone, but the classes directly involved in custom plugins (RPluginInterface and RPluginInfo) are unlikely to change significantly at this point. A QCAD 3.1 Beta release is scheduled to be released in the coming days.

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Call External C Library

Post by matthiaswm » Thu May 16, 2013 9:49 pm

Thanks, that was already a great help.

EDIT3: OK, I get the plugin to work when I use the source tree. So obviously the issues are with configuring for deployment (OS X typical) and/or differences to 3.0.9. I will continue to develop in the GIT tree in the hopes that the plugin will eventually wrk in the public version.

Thanks,

Matthias

User avatar
andrew
Site Admin
Posts: 9019
Joined: Fri Mar 30, 2007 6:07 am

Re: Call External C Library

Post by andrew » Fri May 17, 2013 11:30 pm

I've just uploaded QCAD 3.1 Beta which has support for these types of C++ plugins.

A new version of the CAM add-on for QCAD is now also available as a first beta version. Although it does not compute tool radius compensation, it might still be interesting to try it out. Please refer to this thread for details:
viewtopic.php?f=17&t=2078&p=7850#p7850

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Call External C Library

Post by matthiaswm » Sat May 18, 2013 11:20 pm

OK, that works. Great! I bought the CAM addition and I can run a binary plugin and methods in it. Getting closer to running the Laser ;-)

User avatar
andrew
Site Admin
Posts: 9019
Joined: Fri Mar 30, 2007 6:07 am

Re: Call External C Library

Post by andrew » Sun May 19, 2013 3:57 pm

Excellent! That is quite impressive without any further instructions :) Let me know if you hit any brick walls.

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Call External C Library

Post by matthiaswm » Mon May 20, 2013 10:16 pm

Thanks. With all the code available, I had a fair chance of digging up things that work.

I currently have a binary plugin that talks USB (libusb is very nice!) and makes a QObject available named RLaser. I can then call RLaser.move Home(), etc. from any script file. I also added a dockable box for basic Laser Cutter control (see snapshot, to be expanded).

With the CAM output dialog, there is room for improvement.

I think that the layers should not be in a pulldown menu, but instead all layers should be visible in a scrollable multi-column view. It should be possible to sort the layers, so text marking comes before cutting, for example.

There should be one check box per layer (second column) to switch CAM export off for that layer alone. The following columns can then be managed by the CAM plugin (for the laser, that would be a pulldown (cut/engrave), power and speed (or even better, a pulldown with presets)). The settings would be saved with the layer in the .dxf file.

Also, from within the plugin, I would like to be able to send the data directly to the laser instead of saving them in a file.

Code: Select all

Sample Column View:

| 0 Draft | [ ] |
| 1 Text  | [X] |   Cut   [V] | Pwr:  20% | Spd: 100% |
| 2 CutMe | [X] |   Cut   [V] | Pwr: 100% | Spd:   6% |
| 3 Cut2  | [X] |   Cut   [V] | Birch [V] |       3mm |
| 4 Img   | [X] | Engrave [V] | Pwr:  15% | Spd: 500% | Dithered [V] |

[X] = Checkbox, [V] = Pulldown Menu
Attachments
QCADSnap.png
Very first invocation of a Laser Machine Control Panel. USB connection via C++ Qt Plugin.
QCADSnap.png (38.07 KiB) Viewed 20985 times

User avatar
andrew
Site Admin
Posts: 9019
Joined: Fri Mar 30, 2007 6:07 am

Re: Call External C Library

Post by andrew » Mon May 20, 2013 10:55 pm

Thanks for the input.

The two panels at the right side of the CAM export dialog ("Global options" and "Layer options") are very flexible and configurable.

For example, the configuration "GCode" is based on the file "scripts/Cam/CamConfigurations/GCode.js".
In the constructor, this exporter defines the files "GCode.ui" and "GCodeLayer.ui" to be the global and layer specific option panels to be shown for that configuration. Your own configuration can for example inherit GCode but use different global options and layer specific options. You can use "Qt Designer" to design such individual option panels (.ui files). Object names that are used for the widgets in the .ui file are directly mapped to document variables and layer properties.

Example:
We want to create a new configuration called "MyLaser", based on "GCode". But instead of GCode.ui and GCodeLayer.ui, we want to use our own .ui files:

File "MyLaser.js"

Code: Select all

include("GCode.js");

function MyLaser(documentInterface, newDocumentInterface) {
    GCode.call(this, documentInterface, newDocumentInterface);

    this.globalOptions = "MyLaser";
    this.layerOptions = "MyLaserLayer";
}

MyLaser.prototype = new GCode();
MyLaser.ui contains one combo box with its object name set to "Power".
MyLaserLayer.ui contains one combo box with its object name also set to "Power".

The power chosen as global option is then accessible in MyLaser.js as document variable:

Code: Select all

var powerGlobal = this.document.getVariable("Cam/Power");
The power chosen for the layer which is currently being processed is accessible as layer property:

Code: Select all

var layer = this.document.queryLayer(this.getEntity().getLayerId());
var powerLayer = layer.getCustomProperty("Cam/Power", powerGlobal);      // default to globally set power
Document variables and layer properties can be saved to the DXF file if XData is enabled. Since XData support is considered experimental, you will have to enable it on the command line when starting QCAD:

Code: Select all

./qcad -enable-xdata
That's probably a lot of information to digest. The reason for this relatively complex design is flexibility. The information that has to be collected from the user greatly depends on the configuration and the target machine. Configurations might use lists, tables, combo boxes, check boxes, line edits or even multiline text fields. This is somewhat unpredictable at this point, but I didn't want to impose any unnecessary limits for the user interface. Users are usually more creative than expected at first ;) If someone only engraves text for example, an exporter might only ask for a line of text and a font and not even require any CAD input.

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”