本帖子已过去太久远了,不再提供回复功能。Qt 插件篇 - CSDN博客
QT有着独特的插件管理方法便于使用,调理清晰.完全可以替代WIN32下的动态库,静态库.不过,QT也支持动态库和静态库加载.见QLibrary,最终,QLibrary调用WIN32下的LoadLibrary,GetProcAddress函数.
Qt插件的使用方法:
[1]project_main_1工程中定义接口
class&interface__1
&&&&void&__func1()&=&0;
&&&&void&__func2()&=&0;
&&&&void&__func3()&=&0;
&&&&class&interface__2
&&&&void&__func4()&=&0;
&&&&void&__func5()&=&0;
&&&&void&__func6()&=&0;
[2]project_plugin_1工程中实现接口
class&derive__1:public&interface__1,interface__2
&&&&void&__func1();
&&&&void&__func2();
&&&&void&__func3();
&&&&void&__func4();
&&&&void&__func5();
&&&&void&__func6();
[3]project_main_1中使用QPluginLoader,QPluginLoader内部实现也是使用LoadLibrary,GetProcAddress,稍后会有说明
QobjectList&objList&=&QpluginLoader::staticInstances();
for(int&i&=&0;&i&objList.size();&i++)
&&&&interface__1&*inter1&=&qobject_cast&&interface__1&*&(objList[i]);
&&&&interface__2&*inter1&=&qobject_cast&&interface__2&*&(objList[i]);&&&&
QpluginLoader&pl(“plugin&path”);
Qobject*&plugin&=&pl.instance();
这里可以看出,充分的使用了对象对象的多态.那么,是QpluginLoader是如何实现的呢?
看下面细节.
Qt的类几乎所有的都有一个QT_class+private的类,用来实现具体逻辑,暴露给我们的类定义通用的接口.QpluginLoader的内部类是QLibraryPrivate,与QLibrary是同一个.
[1]如何加载
bool&QLibraryPrivate::loadPlugin()
&&&&if&(instance)&{
&&&&&&&&libraryUnloadCount.ref();
&&&&&&&&return&true;
&&&&if&(load())&{//这里最终调用load_sys()
&&&&&&&&instance&=&&&&(QtPluginInstanceFunction)resolve(&qt_plugin_instance&);//注意这里的&qt_plugin_instance,插件里面必然导出该函数名称
&&&&&&&&return&
&&&&return&false;
bool&QLibraryPrivate::load_sys()
#ifdef&Q_OS_WINCE
&&&&QString&attempt&=&QFileInfo(fileName).absoluteFilePath();
&&&&QString&attempt&=&fileN
&&&&//avoid&'Bad&Image'&message&box
&&&&UINT&oldmode&=&SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
&&&&pHnd&=&LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
&&&&if&(pluginState&!=&IsAPlugin)&{
&&&&&&&&if&(!pHnd&&&&::GetLastError()&==&ERROR_MOD_NOT_FOUND)&{
&&&&&&&&&&&&attempt&+=&QLatin1String(&.dll&);
&&&&&&&&&&&&pHnd&=&LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
&&&&SetErrorMode(oldmode);
&&&&if&(!pHnd)&{
&&&&&&&&errorString&=&QLibrary::tr(&Cannot&load&library&%1:&%2&).arg(fileName).arg(qt_error_string());
&&&&if&(pHnd)&{
&&&&&&&&errorString.clear();
&&&&&&&&wchar_t&buffer[MAX_PATH];
&&&&&&&&::GetModuleFileName(pHnd,&buffer,&MAX_PATH);
&&&&&&&&attempt&=&QString::fromWCharArray(buffer);
&&&&&&&&const&QDir&dir&=&&QFileInfo(fileName).dir();
&&&&&&&&const&QString&realfilename&=&attempt.mid(attempt.lastIndexOf(QLatin1Char('\\'))&+&1);
&&&&&&&&if&(dir.path()&==&QLatin1String(&.&))
&&&&&&&&&&&&qualifiedFileName&=&
&&&&&&&&else
&&&&&&&&&&&&qualifiedFileName&=&dir.filePath(realfilename);
&&&&return&(pHnd&!=&0);
[2]qt_plugin_instance是定义导出的呢?
在实现接口时,必须加上Q_EXPORT_PLUGIN2,Q_EXPORT_PLUGIN2
(PluginName,ClassName)
#&&define&Q_EXPORT_PLUGIN2(PLUGIN,&PLUGINCLASS)&&&&&&\
&&&&&&&&&&&&Q_PLUGIN_VERIFICATION_DATA&\
&&&&&&&&&&&&Q_EXTERN_C&Q_DECL_EXPORT&\
&&&&&&&&&&&&const&char&*&Q_STANDARD_CALL&qt_plugin_query_verification_data()&\
&&&&&&&&&&&&{&return&qt_plugin_verification_&}&\
&&&&&&&&&&&&Q_EXTERN_C&Q_DECL_EXPORT&QT_PREPEND_NAMESPACE(QObject)&*&Q_STANDARD_CALL&qt_plugin_instance()&\
&&&&&&&&&&&&Q_PLUGIN_INSTANCE(PLUGINCLASS)
#&&define&Q_PLUGIN_VERIFICATION_DATA&\
&&&&static&const&char&*qt_plugin_verification_data&=&\
&&&&&&&pattern=&&QT_PLUGIN_VERIFICATION_DATA&&\n&&\
&&&&&&&version=&QT_VERSION_STR&\n&&\
&&&&&&&debug=&QPLUGIN_DEBUG_STR&\n&&\
&&&&&&&buildkey=&QT_BUILD_KEY;
#define&&Q_EXTERN_C&extern
#define&&Q_DECL_EXPORT&__declspec(dllexport)
#define&Q_PLUGIN_INSTANCE(IMPLEMENTATION)&\
&&&&&&&&{&\
&&&&&&&&&&&&static&QT_PREPEND_NAMESPACE(QPointer)&QT_PREPEND_NAMESPACE(QObject)&&_&\
&&&&&&&&&&&&if&(!_instance)&&&&&&\
&&&&&&&&&&&&&&&&_instance&=&new&IMPLEMENTATION;&\
&&&&&&&&&&&&return&_&\
去掉宏之后,是2个函数.
static&const&char&*qt_plugin_verification_data&=&&&&&&&&&&&&pattern=&&QT_PLUGIN_VERIFICATION_DATA&&\n&&&&&&&version=&QT_VERSION_STR&\n&&
&&&&&debug=&QPLUGIN_DEBUG_STR&\n&
&&&&&&&&&&&buildkey=&QT_BUILD_KEY;
extern&__declspec(dllexport)&qt_plugin_query_verification_data()
&&&&return&&qt_plugin_verification_
extern&__declspec(dllexport)&QObject*&qt_plugin_instance()
&&&&Qpoint&QOjbect&&_
&&&&if&(!_instance)
&&&&&&&&&&&&&&&&_instance&=&new&PLUGINCLASS;
&&&&&&&&&&&&return&_
instance是QObject&*(*QtPluginInstanceFunction)();
这样就实现了的插件但是还没完
在定义接口时,还应加上Q_DECLARE_INTERFACE,This
macro associates the given Identifier (a string literal) to the interface class called ClassName. The Identifier must be unique.
#&&define&Q_DECLARE_INTERFACE(IFace,&IId)&\
&&&&template&&&&inline&const&char&*qobject_interface_iid&IFace&*&()&\
&&&&{&return&IId;&}&\
&&&&template&&&&inline&IFace&*qobject_cast&IFace&*&(QObject&*object)&\
&&&&{&return&reinterpret_cast&IFace&*&((object&?&object-&qt_metacast(IId)&:&0));&}&\
&&&&template&&&&inline&IFace&*qobject_cast&IFace&*&(const&QObject&*object)&\
&&&&{&return&reinterpret_cast&IFace&*&((object&?&const_cast&QObject&*&(object)-&qt_metacast(IId)&:&0));&}
#endif&//&Q_MOC_RUN
本文已收录于以下专栏:
相关文章推荐
http://blog.csdn.net/liuysheng/article/details/6758590
QT有着独特的插件管理方法便于使用,调理清晰.完全可以替代WIN32下的...
Qt有两种与插件有关的API。一种用来扩展Qt本身的功能,如自定义数据库驱动,图像格式,文本编解码,自定义分格,等等,称为Higher-Level API 。另一种用于应用程序的功能扩展,称为Lowe...
环境介绍QWT,全称是Qt Widgets for Technical Applications,是一个基于LGPL版权协议的开源项目,可生成各种统计图。它为具有技术专业背景的程序提供GUI组件和一组...
&使用ctkPluginFramework插件系统构建项目实战&,这篇文章是写博客以来最纠结的一篇文章。倒不是因为技术都多么困难,而是想去描述一个项目架构采用ctkPluginFramework来构建...
他的最新文章
讲师:王禹华
讲师:宋宝华
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)