Qt QPluginLoader.instance()-它实际上是如何工作的?

Qt QPluginLoader.instance()-它实际上是如何工作的?,qt,dll,constructor,Qt,Dll,Constructor,我目前正在从事一个以动态插件加载为中心的Qt项目。我正在使用Qt的QPluginLoader加载DLL。通过CameraPluginStructs访问不同的插件,定义如下: struct CameraPluginStruct { QString name; QString filePath; CameraPluginInterface* plugin; QPluginLoader* pluginLoader; CameraPluginStruct(QSt

我目前正在从事一个以动态插件加载为中心的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);
   }
}
我制作了一些简单的测试插件,在调用构造函数时将消息写入控制台。为简单起见,假设我有两个测试插件,DLL A和DLL B。当我使用loadPlugin()函数加载A时,将调用插件中的构造函数,并在控制台中写入相应的消息。我可以用B做同样的事情,一切似乎都正常——B的构造函数消息被写入控制台,其他函数也正常工作

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

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

“返回插件的根组件对象。(…)该组件对象是一个QObject。使用QObject_cast()访问您需要的接口。” 对……感兴趣。”

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

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

“QPluginLoader的多个实例可用于访问同一物理插件。”

因此,无论如何,我看不出这是问题的根源

如果有人能澄清QPluginLoader.instance()是如何工作的,我将不胜感激。为什么构造函数(至少看起来是这样)只在我第一次使用instance()调用时才被调用

谢谢大家!

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

TestDLL::TestDLL()
{

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


如果需要更多,则创建一个
createInstance()
clone()
方法,以便可以从根实例创建新实例。或者更传统地,将插件类设置为要公开的类类型的工厂。

这是一个旧线程,但我仍然注意到,您使用的
qobject\u cast
并不完全正确。无论何时使用
qobject\u cast
dynamic\u cast
等。您应该始终检查该强制转换的结果。如果强制转换失败,则返回0。在您的情况下,您有
possiblePlugin
,在我看来,如果它不等于0,您认为您肯定有您类型的插件,这可能并不总是如此。
void unloadPlugin(CameraPluginStruct& p)
{
    p.pluginLoader->unload();  // QPluginLoader.unload(); 
    p.pluginLoader->~QPluginLoader();

    p.pluginLoader = nullptr;
    p.plugin = nullptr;
 }
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;
}