Access to signal arguments in qt_metacall?
-
I'm having troubles finding how to access arguments passed to a signal from a custom qt_metacall implementation.
@bool QClrSlotBridge::emitSignal(char *signature, void **arguments)
{
int signalIndex = indexOfSignal(signature);
if (signalIndex >= 0) {
QMetaObject::activate(this,
signalIndex, arguments);
return true;
} else {
return false;
}
}int QClrSlotBridge::qt_metacall(QMetaObject::Call call,
int id, void **arguments)
{
int internalId = QObject::qt_metacall(call, id, arguments);
if (internalId == -1 || call != QMetaObject::InvokeMetaMethod)
return internalId;id -= 15; Q_ASSERT(id < slotList.size()); slotList[id]->call(arguments); return -1;
}
@If I run code that looks like this:
@void* argv[] = { somePassedInArgument };
QClrSlotBridge->emitSignal("something(void*)", argv);
@how would I access somePassedInArgument in qt_metacall? arguments[0] (which I think is reserved for a return value pointer) is NULL (as expected) but arguments[1] is also NULL and I think this should hold a pointer to somePassedInArgument.
-
Hi,
What do you mean by custom qt_metacall ? Are you trying to do the job of moc yourself ?
-
Then I would recommend that you first get familiar with it. moc (the meta object compiler) takes a QObject header as input and generates the code you are trying to write by hand
-
Signals and Slots always are dynamic - in the sense that you setup the connections between objects at runtime by using connect(). But which Slots or Signals an object has is defined by its class. And in C++ the class is fixed at compile time (this is not specific to Qt at all). The only thing that is specific to Qt is that you need to to process your header files with MOC and compile MOC's output into your binary. This makes the Signals and Slot "magic" work.
Recommended reading:
http://qt-project.org/doc/qt-4.8/moc.html -
[quote author="JohnAC" date="1398720758"]And I'm not wanting to define slots/signals at compile time[/quote]
Can you explain why this is required?
[quote author="JohnAC" date="1398720758"]my code is using QMetaObject directly to connect and emit signals[/quote]
Connections between Signals and Slots are always set up at run time, using QObject:connect(). Also signals are always emitted at runtime, using the "emit" keyword. What is fixed at compile-time is which Signals and/or Slots a specific class offers. And that's no different from "regular" member functions.
-
bq. Can you explain why this is required?
Because the slots and signals being used aren't known at compile time. I'm binding to language (C#) that plainly requires the capability of defining the slots and signals at runtime.
I've been following this to get as far as I have: http://doc.qt.digia.com/qq/qq16-dynamicqobject.html
And it mostly works, I just can't access the arguments being passed through within my slot handling code.
-
[quote author="JohnAC" date="1398721473"]bq. Can you explain why this is required?
Because the slots and signals being used aren't known at compile time.[/quote]
And they don't have to. You can have an arbitrary number of Signals and/or Slots in your classes and still only connect to a small subset of those at runtime. That's perfectly normal. Most of the original Qt classes will have lots of Signals and Slots that you'll never use in your application at runtime.
[quote author="JohnAC" date="1398721473"]I'm binding to language (C#) that plainly requires the capability of defining the slots and signals at runtime.[/quote]
I'm not so sure about this yet ;-)
My experience in C# is a bit limited, but AFAIK classes in C# are also fixed at compile-time, i.e. adding a method to a class at runtime is not possible in C# either (unlike e.g. Python). So when/why exactly do you need to add a Signal or Slot to your C++ class at runtime? Can you give an example?
-
Sigh...
You're right about C# in a way - classes are immutable, you can't add or remove members to/from types at runtime.
C# uses Qt through a glue library. This glue library has no knowledge of the C# project at all and, thus, cannot use moc to compile signal and slot definitions.
The way the C# code is working is by using a type initalizer (not sure if C++ has these). It's basically a static constructor that's invoked when a Type is first encountered at runtime. Anyway, the initalizer will then perform what is analogous to moc - it will read metadata from the class definition and instruct the glue library to create a dynamic signal/slot object that can be used for connections later.
-
Ah, it becomes more clear now. But wouldn't it be possible to have some kind of native "proxy" class on the C++ side that acts on behalf of the managed C# class? The native class, derived from QObject, could then be processed by MOC as usual, establish connections via QObject::connect() and so on. Finally, that "proxy" class could be "wrapped for use by C#":http://msdn.microsoft.com/en-us/library/ms235281.aspx.
-
Yes that would be possible but a 1:1 relationship betwen C# and C++ types is very undesirable. Each time I, or another developer, wanted to define a type to interop with Qt in this way would also have to write a C++ class to go with it, compile the library with the definitions etc.
Anyway, I've been talking with thiago on IRC and we discovered that the issue I'm running into is due to the sender and receiver being on different threads and the queued emit code not having enough information regarding the arguments being passed.