我目前正在开发一个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;
}
答案 0 :(得分:2)
当你的插件被加载时(即第一次调用QPluginLoader::instance()
),然后创建它的单个实例 - 这是你的根实例。根实例是唯一为您创建的QPluginLoader
实例。
如果您需要更多,则为插件类创建createInstance()
或clone()
方法,以便可以从根实例创建新实例。或者更常规的是,使您的插件类成为您希望公开的类类型的 factory 。