QPluginLoader.instance() - 它是如何工作的?
QPluginLoader.instance() - how does it really work?
我目前正在从事一个以动态插件加载为中心的 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 的构造函数消息被写入控制台,其他函数似乎也能正常工作。
现在,当我尝试创建另一个连接到 A 或 B 的 CameraPluginStruct 时出现问题。没有消息写入控制台,这让我认为没有调用构造函数。尽管如此,我还是能够成功调用插件中的其他测试函数(DoSomething(),见下文)。如果我卸载连接到 A 或 B 的所有 CameraPlugins,然后再次加载 DLL,则在第一次加载时再次调用构造函数。
QPluginLoader.instance()调用在文档中描述如下:
"Returns the root component object of the plugin. (...) The component object is a QObject. Use qobject_cast() to access interfaces you are
interested in." http://doc.qt.io/qt-5/qpluginloader.html#instance
DLL 中的构造函数每次都会被调用,而不仅仅是第一次,这不是很自然吗?
据我所知,对于任何程序,DLL 只加载一次。因此,我也尝试在每个 DLL 文件中只使用一个 QPluginLoader,结果相同。 Qt 还说:
"Multiple instances of QPluginLoader can be used to access the same physical plugin." 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;
}
加载插件时(即第一次调用 QPluginLoader::instance()
),然后会创建一个 单个 实例 - 这是您的根实例。根实例是 QPluginLoader
将为您创建的唯一实例。
如果您想要更多,则可以为您的插件 class 创建一个 createInstance()
或 clone()
方法,以便可以从根实例创建新实例。或者更传统的做法是,将你的插件 class 设为你希望公开的 class 类型的 factory。
我目前正在从事一个以动态插件加载为中心的 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 的构造函数消息被写入控制台,其他函数似乎也能正常工作。
现在,当我尝试创建另一个连接到 A 或 B 的 CameraPluginStruct 时出现问题。没有消息写入控制台,这让我认为没有调用构造函数。尽管如此,我还是能够成功调用插件中的其他测试函数(DoSomething(),见下文)。如果我卸载连接到 A 或 B 的所有 CameraPlugins,然后再次加载 DLL,则在第一次加载时再次调用构造函数。
QPluginLoader.instance()调用在文档中描述如下:
"Returns the root component object of the plugin. (...) The component object is a QObject. Use qobject_cast() to access interfaces you are interested in." http://doc.qt.io/qt-5/qpluginloader.html#instance
DLL 中的构造函数每次都会被调用,而不仅仅是第一次,这不是很自然吗?
据我所知,对于任何程序,DLL 只加载一次。因此,我也尝试在每个 DLL 文件中只使用一个 QPluginLoader,结果相同。 Qt 还说:
"Multiple instances of QPluginLoader can be used to access the same physical plugin." 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;
}
加载插件时(即第一次调用 QPluginLoader::instance()
),然后会创建一个 单个 实例 - 这是您的根实例。根实例是 QPluginLoader
将为您创建的唯一实例。
如果您想要更多,则可以为您的插件 class 创建一个 createInstance()
或 clone()
方法,以便可以从根实例创建新实例。或者更传统的做法是,将你的插件 class 设为你希望公开的 class 类型的 factory。