QPluginLoader.instance() - 它是如何工作的?

时间:2015-04-16 12:45:27

标签: qt dll constructor

我目前正在开发一个Qt项目,其中动态插件加载是核心。我正在使用Qt的 QPluginLoader 加载DLL。可以通过CameraPluginStructs访问不同的插件,定义如下:

struct CameraPluginStruct
{
    QString name;
    QString filePath;
    CameraPluginInterface* plugin;
    QPluginLoader* pluginLoader;

    CameraPluginStruct(QString filePath=nullptr, QString name=nullptr):
         filePath(filepath), name(name), plugin(nullptr), pluginLoader(nullptr){}
};

要加载插件,请调用以下函数:

void loadPlugin(CameraPluginStruct& p)
{
    p.pluginLoader = new QPluginLoader(p.filePath);
    p.pluginLoader->load();

    QObject* possiblePlugin = p.pluginLoader->instance(); //QPluginLoader.instance();

   if(possiblePlugin) 
   {
       // cast from QObject to correct type:
       p.plugin = qobjectcast<CameraPluginInterface>(possiblePlugin);
   }
}

要卸载插件,我使用此功能:

void unloadPlugin(CameraPluginStruct& p)
{
    p.pluginLoader->unload();  // QPluginLoader.unload(); 
    p.pluginLoader->~QPluginLoader();

    p.pluginLoader = nullptr;
    p.plugin = nullptr;
 }

我做了一些简单的测试插件,在调用构造函数时将消息写入控制台。为简单起见,我们假设我有两个测试插件,DLL A和DLL B.当我使用 loadPlugin()函数加载A时,调用插件中的构造函数,并且相应的消息写入控制台。我可以用B做同样的事情,一切似乎都有效 - B&#39的构造函数消息被写入控制台,其他函数似乎也能正常工作。

现在,当我尝试创建另一个连接到A或B的CameraPluginStruct时会出现问题。没有消息写入控制台,这导致我认为没有调用构造函数。即使我能够成功调用插件中的其他测试函数( DoSomething(),见下文)。如果我卸载连接到A或B的所有CameraPlugins,然后再次加载DLL,则会在第一次加载时再次调用构造函数。

QPluginLoader.instance()调用在文档中描述如下:

  

&#34;返回插件的根组件对象。 (...)组件对象是QObject。使用qobject_cast()访问您的接口   对。&#34; http://doc.qt.io/qt-5/qpluginloader.html#instance

感兴趣

那么,每次调用DLL中的构造函数是不是很自然,而不仅仅是第一次?

据我所知,DLL只为任何程序加载一次。因此,我也尝试每个DLL文件只使用一个 QPluginLoader ,结果相同。 Qt还说:

  

&#34; QPluginLoader的多个实例可用于访问同一个物理插件。&#34; http://doc.qt.io/qt-5/qpluginloader.html#details

因此,无论如何,我无法看到这是如何成为问题的根源。

如果有人能澄清 QPluginLoader.instance()是如何工作的,我真的很感激。为什么构造函数 - 至少看起来如何 - 仅在我第一次使用 instance()调用时调用?

谢谢!

以下是DLL中的代码(输出文本在A和B中有所不同):

TestDLL::TestDLL()
{
    std::cout << "This is written from the constructor in A \n";
}

QString TestDLL::Name() const
{
    return "Hello, writing from Name() \n";
}

void TestDLL::DoSomething() const
{
   qDebug() << "Hello, this text comes from DoSomething()"\n;
}

1 个答案:

答案 0 :(得分:2)

当你的插件被加载时(即第一次调用QPluginLoader::instance()),然后创建它的单个实例 - 这是你的根实例。根实例是唯一为您创建的QPluginLoader实例。

如果您需要更多,则为插件类创建createInstance()clone()方法,以便可以从根实例创建新实例。或者更常规的是,使您的插件类成为您希望公开的类类型的 factory