【发布时间】:2013-02-06 10:48:17
【问题描述】:
Qt 插件是否存在一种方法来确定它是静态初始化还是动态初始化?如果是动态初始化的,插件是否有办法确定其动态库(.dll 或 .so)的路径?
【问题讨论】:
Qt 插件是否存在一种方法来确定它是静态初始化还是动态初始化?如果是动态初始化的,插件是否有办法确定其动态库(.dll 或 .so)的路径?
【问题讨论】:
QPluginLoader 有两个函数,你可以看看:
a)QObjectList QPluginLoader::staticInstances ()
返回插件加载器持有的静态插件实例(根组件)的列表。
b)QString fileName () const
此属性保存插件的文件名。 要可加载,文件的后缀必须是符合平台的可加载库的有效后缀,例如Unix 上的 .so、Mac OS X 上的 .dylib 和 Windows 上的 .dll。后缀可以通过 QLibrary::isLibrary() 进行验证。
不幸的是,如果您没有特定插件的插件加载器,那么您无能为力。插件不需要任何特殊接口,可以直接从QObject派生。使用Q_EXPORT_PLUGIN2 导出插件只会声明QObject 指向带有qt_plugin_instance 前缀的插件实例的指针。
加载插件不会调用任何特定函数,所以我看不到将其提供给插件本身的方法。
但是,如果您愿意失去可移植性,您可以做一些事情:在 Windows 上,插件只是 dll,可通过 internally by Qt via standard Windows system calls 访问(例如,它们是使用 LoadLibrary 函数加载的,找到指向过程的指针使用GetProcAddress,它们是通过FreeLibrary调用发布的),所以你可以试试this approach(我还没有测试过,这是一个丑陋的hack,但它可能会起作用)。
// near the top of your CPP file
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
// and then, anywhere you need it:
LPTSTR strDLLPath1 = new TCHAR[_MAX_PATH];
::GetModuleFileName((HINSTANCE)&__ImageBase, strDLLPath1, _MAX_PATH);
似乎任何使用 VS2002(及更高版本)链接器编译的 EXE 或 DLL 都提供了一个名为 __ImageBase 的伪变量,它表示模块的 DOS 头(所有 32 位二进制文件都有这个)。只需将此变量转换为 HINSTANCE,即可将其作为第一个参数传递给 GetModuleFileName()。
在 Unix 系统上,plugins are loaded via standard dlopen() system call,因此您可以使用来自 here 的解决方案。
【讨论】:
staticInstances() 可能有用,但不是fileName(),因为动态插件不会自行加载,因此无法访问加载它的QPluginLoader 实例。