PDA

View Full Version : Instantiate objects only having their class name



victor.fernandez
30th June 2009, 17:05
Hi! I have a QThread where I perform SQL queries. Now that my application has grown, I want to many it modular by creating modules that live in that thread, i.e. classes that are instantiated and perform their work in that thread.

However, I would like to do it in a way the QThread doesn't need to know of each of the classes it has. It would just get the list of class names and instantiate them without needing to know which are their constructors.

I thought of registering every module as a metatype, then passing the class name to the QThread and using QMetaType::construct() in it to be able to instantiate them. It would look like this:



class DbThread : public QThread
{
Q_OBJECT

public:
DbThread(QObject *parent = 0);
void constructExtensions();
void queryExtensions();
void registerExtension(const QString& type);

private:
QStringList m_extensionNames;
QList<Extension*> m_extensions;
};


void DbThread::constructExtensions()
{
foreach(const QString& className, m_extensionNames) {
QByteArray classNameBA = className.toLocal8Bit();
int id = QMetaType::type(classNameBA.constData());
if(id != -1) {
void *myClassPtr = QMetaType::construct(id);
if(myClassPtr == 0) {
qDebug() << "Failed instantiating the module:" << className;
continue;
}
Extension *extension = (Extension*) myClassPtr;
extension->setParent(this);
m_extensions.append(extension);
}
}
}


void DbThread::queryExtensions()
{
foreach(Extension *ext, m_extensions)
ext->doSomething();
}


void DbThread::registerExtension(const QString& type)
{
m_extensionNames << type;
}


I use the class Extension which is in fact an interface. Other modules are subclasses of it. For example:



#include <QMetaType>
#include <QObject>
#include <QString>
#include "extension.h"

class CoolExtension : public Extension
{
Q_OBJECT

public:
CoolExtension(QObject *parent = 0);
CoolExtension(const CoolExtension& other);
void doSomething();
};

Q_DECLARE_METATYPE(CoolExtension)


Then I would call DbThread::registerExtension("CoolExtension") so that constructExtensions() would instantiate one object of the CoolExtension class.

That is the idea. However the application segfaults after I try to use the pointer QMetaType::construct() gave me. The pointer is not null but it seems QMetaType::construct() is not doing what I expect or I can't convert it properly. What might be wrong?

Do you have a better idea on how to create modules that must be instantiated by a QThread since they live in it? Perhaps should I instantiate them somewhere else and use QThread::moveToThread()? But I don't like the idea of instantiating in one thread and moving to another one.

Thanks.

wysota
30th June 2009, 17:22
You have to register "pointers to classes" as the metatype, not classes themselves. Although I'm not sure construction will work properly with pointers. It might be much easier if you just provided factories for the classes using the plugin infrastructure.