I'm writing an application that loads plugins, and each plugin acts as a factory for QObject subclasses. The application sends parameters to a plugin to instantiate an object, and each object uses different parameters to be created.
This is all working pretty well, however the parameters change between plugins and objects, and it would be nice if the application had a mode to report the parameters needed to construct an object. Objects are created by a config file, so the author of the config needs to know the required parameters to provide, especially if they change.
So I've been looking into Qt's MetaObject system, which is perfect for this use case, because I can create a message that will report the shape of an object's constructor using Q_INVOKABLE on the constructor and QMetaObject::constructor(int i).
The problem is that I have to use the actual class to get a QMetaObject static instance, and I would like to loop over a list of class names as strings to create this report.
I'm not interested in registering types for use with QVariant, because these objects aren't for copying around or sending over a network or serializing. They may be things connected to hardware or consume lots of memory. All I want is the constructor definition of a plugin's factory objects, but originating from the string name of each class the plugin can construct.
QObject instances provide a QMetaObject, but they don't seem to have an innate QMetaType, which is necessary for:
int typeId = QMetaType::type("MyClass");
const QMetaObject *s = QMetaType::metaObjectForType(typeId);
So instead I have to use
QMetaObject m = MyClass::staticMetaObject;
Which requires each definition to be manually coded into the plugin, as mentioned: How can I find a Qt metaobject instance from a class name?
Because QObject doesn't have a copy constructor, Q_DECLARE_METATYPE() will fail, as well as qRegisterMetaType(), and creating a fake copy constructor to satisfy the compiler is a bad idea, and requiring default constructors are bad as well in this use case.
If the solution is to manually type each class into a function providing this message to the config writer, then it is what it is. However if I'm missing a simpler solution, given that the plugin already provides a string list of available objects and acts as a factory for QObject subclasses (that don't have default constructors), I would like to learn it!
Does someone have a better idea how to do this:
QStringList p;
p << "MyClass";
p << "MyClass2";
for(int pi=0;pi<p.length();pi++)
{
int typeId = QMetaType::type(p[pi]);
const QMetaObject *s = QMetaType::metaObjectForType(typeId);
int c = s->constructorCount();
printf("constructor count: %d\n",c);
for (int i=0;i<c;i++)
{
QMetaMethod m = s->constructor(i);
printf("ctor %d: %s %s %d\n",i,qPrintable(m.name()),qPrintable(m.methodSignature()),m.parameterCount());
int nc = m.parameterCount();
QList<QByteArray> pn = m.parameterNames();
QList<QByteArray> pt = m.parameterTypes();
for (int j=0;j<nc;j++)
{
printf("\t%s %s\n",qPrintable(pt.at(j)),qPrintable(pn.at(j)));
}
}
}
This will crash because typeId == QMetaType::UnknownType
, and therefore s == null
.