C++ plugin, events
Moderator: andrew
Forum rules
Always indicate your operating system and QCAD version.
Attach drawing files, scripts and screenshots.
Post one question per topic.
Always indicate your operating system and QCAD version.
Attach drawing files, scripts and screenshots.
Post one question per topic.
C++ plugin, events
Greetings;
I've been working on a C++ plugin for a while now works with a mechanical arm to plot a slice of an object on a 2d plane.
For all of my testing to this point everything has been done synchronously - is there a way for me to implement events that the scripts can attach to, or a way to call a function that the javascript script has to update the display so that everything can be switched to async methods?
I've been working on a C++ plugin for a while now works with a mechanical arm to plot a slice of an object on a 2d plane.
For all of my testing to this point everything has been done synchronously - is there a way for me to implement events that the scripts can attach to, or a way to call a function that the javascript script has to update the display so that everything can be switched to async methods?
Re: C++ plugin, events
Your plugin can expose a class / methods to ECMAScript.
The example plugin exposes the C++ class "MyClass" and its member functions:
https://github.com/qcad/qcad/tree/maste ... mpleplugin
Bindings are defined in EcmaMyClass and initialised in RExamplePlugin::initScriptExtensions.
The example plugin exposes the C++ class "MyClass" and its member functions:
https://github.com/qcad/qcad/tree/maste ... mpleplugin
Bindings are defined in EcmaMyClass and initialised in RExamplePlugin::initScriptExtensions.
Re: C++ plugin, events
I have a class with exposed functions that I am calling - I'm looking for a slightly more specific thing.
Some of the more intense processes that I have to run (For example, calibrating the device I've made to account for manufacturing size & angle inconsistencies) won't necessarily end if specific criteria aren't met.
Is there a way to expose C++ Event Handlers so they can be hooked by EMCAScript?
Since I'll be waiting for certain criteria to be met once the process has been started, I'd rather not have to loop continuously in the emca script calling one function over and over again if I don't have to.
Any suggestions to avoid that would be really appreciated, thank you
Some of the more intense processes that I have to run (For example, calibrating the device I've made to account for manufacturing size & angle inconsistencies) won't necessarily end if specific criteria aren't met.
Is there a way to expose C++ Event Handlers so they can be hooked by EMCAScript?
Since I'll be waiting for certain criteria to be met once the process has been started, I'd rather not have to loop continuously in the emca script calling one function over and over again if I don't have to.
Any suggestions to avoid that would be really appreciated, thank you
Re: C++ plugin, events
You could define a signal in your class which you connect in ECMAScript. Your C++ process could then emit the signal when it is done or otherwise wants to communicate with the ECMAScript caller (progress reports, warnings, errors, etc).
myObject.mySignal.connect(this, "mySlot");
Signals can be exposed to ECMAScript like regular functions.
myObject.mySignal.connect(this, "mySlot");
Signals can be exposed to ECMAScript like regular functions.
Re: C++ plugin, events
Thanks for replying andrew; I haven't quite gotten it working yet.
When you say that signals can be exposed like regular functions, this is what that meant to me:
This doesn't compile however, is my lack of experience using signals to blame here?
When you say that signals can be exposed like regular functions, this is what that meant to me:
Code: Select all
//plugin.h
class MyPlugin : public QObject, public RPluginInterface
{
Q_OBJECT
Q_INTERFACES(RPluginInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.qcad.MyPlugin")
#endif
signals:
void valueChanged(int newValue); //the signal I'd like to connect to from EMCAScript
public:
virtual bool init();
virtual void uninit(bool) {}
virtual void postInit(InitStatus status);
virtual void initScriptExtensions(QScriptEngine& engine);
virtual RPluginInfo getPluginInfo();
static QScriptValue InitializeArm(QScriptContext * context, QScriptEngine* engine); //this function has the emit()
static QScriptValue createEZClass(QScriptContext* context, QScriptEngine* engine);
static QScriptValue EZClassToString(QScriptContext *context, QScriptEngine *engine);
static EZClass* getSelfEZClass(const QString& fName, QScriptContext* context);
};
Code: Select all
// ... plugin.cpp
void MyPlugin::initScriptExtensions(QScriptEngine& engine) {
QScriptValue* proto = new QScriptValue(engine.newVariant(qVariantFromValue((EZClass*)0)));
// base class:
QScriptValue dpt = engine.defaultPrototype(qMetaTypeId<QObject*>());
proto->setPrototype(dpt);
REcmaHelper::registerFunction(&engine, proto, EZArmPlugin::EZClassToString, "toString");
REcmaHelper::registerFunction(&engine, proto, EZArmPlugin::InitializeArm,"InitializeArm");
REcmaHelper::registerFunction(&engine, proto, EZArmPlugin::valueChanged,"MySignal"); //My attempt to register it as I normally do with functions
engine.setDefaultPrototype(qMetaTypeId<EZClass*>(), *proto);
//qScriptRegisterMetaType<EZClass*>(&engine, toScriptValue, fromScriptValue, *proto);
QScriptValue ctor = engine.newFunction(EZArmPlugin::createEZClass, *proto, 0);
engine.globalObject().setProperty("EZClass", ctor, QScriptValue::SkipInEnumeration);
}
Re: C++ plugin, events
You're right. You cannot / don't have to register the signal. Qt does that automatically. I've updated the example plugin with a signal and a function to trigger the emittance of the signal from ECMAScript. In your use case, the signal would of course be emitted from C++ directly. The example plugin can be tested as follows:
This would print "Hello" into the command line output of QCAD.
Updated plugin example:
https://github.com/qcad/qcad/tree/maste ... mpleplugin
Code: Select all
var m=new MyClass();
m.mySignal.connect(function() { EAction.handleUserMessage("Hello"); });
m.emitSignal();
Updated plugin example:
https://github.com/qcad/qcad/tree/maste ... mpleplugin
Re: C++ plugin, events
Awesome, I got it working this morning. I just hadn't put the signal in the right class definition
Thanks for your help mate.
Thanks for your help mate.
Re: C++ plugin, events
One more thing I Guess, if you have a moment to spare -
The signal works; the function I specify in the JS runs when I emit it from the C++.
however, I don't have the variable I actually emitted.
Is it possible to have the variables passed to the function, or will I need to expose the variables by making them public and just access them that way?
when I use the script debugger and inspect MyClass I see that it contains mySignal(int)
The signal works; the function I specify in the JS runs when I emit it from the C++.
however, I don't have the variable I actually emitted.
Is it possible to have the variables passed to the function, or will I need to expose the variables by making them public and just access them that way?
Code: Select all
m.mySignal.connect(function() { EAction.handleUserMessage("Hello"); }); //What you did
m.mySignal.connect(function(aVariable) { //How I anticipated I could gain access to the variable emitted
EAction.handleUserMessage(aVariable);
});
Re: C++ plugin, events
Yes, this should definitely work:
This will output "value: 7" in the QCAD command line.
Code: Select all
ecma> o=new MyClass();
MyClass(0x7fc672c5a660)
ecma> o.setInt(7);
undefined
ecma> o.mySignal.connect(function(value) {EAction.handleUserMessage("value: " + value);});
undefined
ecma> o.emitSignal();
undefined
Re: C++ plugin, events
hey andrew, turned out the reason I wasn't seeing the value on my real-world code was because I was attempting to pass back a std::list.
Once I converted to more primitive types all started working well. Thank you!
Once I converted to more primitive types all started working well. Thank you!
Re: C++ plugin, events
OK, good to hear. A Qt type such as QList might be worth a try, though I have to admit that all my signals use more basic types as well.YourRuler wrote:I was attempting to pass back a std::list. Once I converted to more primitive types all started working well.