Qt 插件篇
2015-08-22 23:25
411 查看
QT有着独特的插件管理方法便于使用,调理清晰.完全可以替代WIN32下的动态库,静态库.不过,QT也支持动态库和静态库加载.见QLibrary,最终,QLibrary调用WIN32下的LoadLibrary,GetProcAddress函数.
Qt插件的使用方法:
[1]project_main_1工程中定义接口
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class interface__1
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func1() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func2() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func3() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class interface__2
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func4() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func5() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func6() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
};
[2]project_plugin_1工程中实现接口
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class derive__1:public interface__1,interface__2
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func1();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func2();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func3();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func4();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func5();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func6();
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
};
[3]project_main_1中使用QPluginLoader,QPluginLoader内部实现也是使用LoadLibrary,GetProcAddress,稍后会有说明
用法1:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
QobjectList objList = QpluginLoader::staticInstances();
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
for(int i = 0; i<objList.size(); i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
interface__1 *inter1 = qobject_cast< interface__1 *>(objList[i]);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
interface__2 *inter1 = qobject_cast< interface__2 *>(objList[i]);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
用法2:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
QpluginLoader pl(“plugin path”);
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Qobject* plugin = pl.instance();
这里可以看出,充分的使用了对象对象的多态.那么,是QpluginLoader是如何实现的呢?
看下面细节.
Qt的类几乎所有的都有一个QT_class+private的类,用来实现具体逻辑,暴露给我们的类定义通用的接口.QpluginLoader的内部类是QLibraryPrivate,与QLibrary是同一个.
[1]如何加载
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
bool QLibraryPrivate::loadPlugin()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (instance) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
libraryUnloadCount.ref();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return true;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (load()) {//这里最终调用load_sys()
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");//注意这里的 qt_plugin_instance,插件里面必然导出该函数名称
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return instance;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return false;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
bool QLibraryPrivate::load_sys()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#ifdef Q_OS_WINCE
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
QString attempt = QFileInfo(fileName).absoluteFilePath();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#else
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
QString attempt = fileName;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#endif
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
//avoid 'Bad Image' message box
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (pluginState != IsAPlugin) {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
attempt += QLatin1String(".dll");
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
SetErrorMode(oldmode);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (!pHnd) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (pHnd) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
errorString.clear();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
wchar_t buffer[MAX_PATH];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
::GetModuleFileName(pHnd, buffer, MAX_PATH);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
attempt = QString::fromWCharArray(buffer);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
const QDir dir = QFileInfo(fileName).dir();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (dir.path() == QLatin1String("."))
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
qualifiedFileName = realfilename;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
else
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
qualifiedFileName = dir.filePath(realfilename);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return (pHnd != 0);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
[2]qt_plugin_instance是定义导出的呢?
在实现接口时,必须加上Q_EXPORT_PLUGIN2,Q_EXPORT_PLUGIN2
(PluginName,ClassName)
宏定义:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_PLUGIN_VERIFICATION_DATA \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_EXTERN_C Q_DECL_EXPORT \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return qt_plugin_verification_data; } \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * Q_STANDARD_CALL qt_plugin_instance() \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_PLUGIN_INSTANCE(PLUGINCLASS)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
其中
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
# define Q_PLUGIN_VERIFICATION_DATA \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
static const char *qt_plugin_verification_data = \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"version="QT_VERSION_STR"\n" \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"debug="QPLUGIN_DEBUG_STR"\n" \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"buildkey="QT_BUILD_KEY;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#define Q_EXTERN_C extern
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#define Q_DECL_EXPORT __declspec(dllexport)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (!_instance) \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
_instance = new IMPLEMENTATION; \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return _instance; \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
去掉宏之后,是2个函数.
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
static const char *qt_plugin_verification_data = "pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" "version="QT_VERSION_STR"\n"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"debug="QPLUGIN_DEBUG_STR"\n"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"buildkey="QT_BUILD_KEY;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
extern __declspec(dllexport) qt_plugin_query_verification_data()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return qt_plugin_verification_data;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
extern __declspec(dllexport) QObject* qt_plugin_instance()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Qpoint<QOjbect> _instance;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (!_instance)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
_instance = new PLUGINCLASS;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return _instance;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
[3]instance是typedefQObject *(*QtPluginInstanceFunction)();
这样就实现了QT的插件.但是还没完.
在定义接口时,还应加上Q_DECLARE_INTERFACE,This
macro associates the given Identifier (a string literal) to the interface class called ClassName. The Identifier must be unique.
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
# define Q_DECLARE_INTERFACE(IFace, IId) \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template <> inline const char *qobject_interface_iid<IFace *>() \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return IId; } \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); }
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#endif // Q_MOC_RUN
Qt插件的使用方法:
[1]project_main_1工程中定义接口
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class interface__1
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func1() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func2() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func3() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class interface__2
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func4() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func5() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func6() = 0;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
};
[2]project_plugin_1工程中实现接口
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class derive__1:public interface__1,interface__2
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func1();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func2();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func3();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func4();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func5();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
void __func6();
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
};
[3]project_main_1中使用QPluginLoader,QPluginLoader内部实现也是使用LoadLibrary,GetProcAddress,稍后会有说明
用法1:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
QobjectList objList = QpluginLoader::staticInstances();
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
for(int i = 0; i<objList.size(); i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
interface__1 *inter1 = qobject_cast< interface__1 *>(objList[i]);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
interface__2 *inter1 = qobject_cast< interface__2 *>(objList[i]);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
用法2:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
QpluginLoader pl(“plugin path”);
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Qobject* plugin = pl.instance();
这里可以看出,充分的使用了对象对象的多态.那么,是QpluginLoader是如何实现的呢?
看下面细节.
Qt的类几乎所有的都有一个QT_class+private的类,用来实现具体逻辑,暴露给我们的类定义通用的接口.QpluginLoader的内部类是QLibraryPrivate,与QLibrary是同一个.
[1]如何加载
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
bool QLibraryPrivate::loadPlugin()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (instance) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
libraryUnloadCount.ref();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return true;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (load()) {//这里最终调用load_sys()
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");//注意这里的 qt_plugin_instance,插件里面必然导出该函数名称
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return instance;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return false;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
bool QLibraryPrivate::load_sys()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#ifdef Q_OS_WINCE
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
QString attempt = QFileInfo(fileName).absoluteFilePath();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#else
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
QString attempt = fileName;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
#endif
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
//avoid 'Bad Image' message box
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (pluginState != IsAPlugin) {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
attempt += QLatin1String(".dll");
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
SetErrorMode(oldmode);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (!pHnd) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (pHnd) {
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
errorString.clear();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
wchar_t buffer[MAX_PATH];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
::GetModuleFileName(pHnd, buffer, MAX_PATH);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
attempt = QString::fromWCharArray(buffer);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
const QDir dir = QFileInfo(fileName).dir();
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (dir.path() == QLatin1String("."))
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
qualifiedFileName = realfilename;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
else
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
qualifiedFileName = dir.filePath(realfilename);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return (pHnd != 0);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
[2]qt_plugin_instance是定义导出的呢?
在实现接口时,必须加上Q_EXPORT_PLUGIN2,Q_EXPORT_PLUGIN2
(PluginName,ClassName)
宏定义:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_PLUGIN_VERIFICATION_DATA \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_EXTERN_C Q_DECL_EXPORT \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return qt_plugin_verification_data; } \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * Q_STANDARD_CALL qt_plugin_instance() \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
Q_PLUGIN_INSTANCE(PLUGINCLASS)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
其中
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
# define Q_PLUGIN_VERIFICATION_DATA \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
static const char *qt_plugin_verification_data = \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"version="QT_VERSION_STR"\n" \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"debug="QPLUGIN_DEBUG_STR"\n" \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"buildkey="QT_BUILD_KEY;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#define Q_EXTERN_C extern
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#define Q_DECL_EXPORT __declspec(dllexport)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (!_instance) \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
_instance = new IMPLEMENTATION; \
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return _instance; \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
去掉宏之后,是2个函数.
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
static const char *qt_plugin_verification_data = "pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" "version="QT_VERSION_STR"\n"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"debug="QPLUGIN_DEBUG_STR"\n"
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
"buildkey="QT_BUILD_KEY;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
extern __declspec(dllexport) qt_plugin_query_verification_data()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return qt_plugin_verification_data;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
extern __declspec(dllexport) QObject* qt_plugin_instance()
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
Qpoint<QOjbect> _instance;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
if (!_instance)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
_instance = new PLUGINCLASS;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return _instance;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
[3]instance是typedefQObject *(*QtPluginInstanceFunction)();
这样就实现了QT的插件.但是还没完.
在定义接口时,还应加上Q_DECLARE_INTERFACE,This
macro associates the given Identifier (a string literal) to the interface class called ClassName. The Identifier must be unique.
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
# define Q_DECLARE_INTERFACE(IFace, IId) \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template <> inline const char *qobject_interface_iid<IFace *>() \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return IId; } \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); }
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#endif // Q_MOC_RUN
相关文章推荐
- QtWebKit插件设计
- Qt 编码问题QTextCodec
- Qt 插件篇
- QT跨线程的信号与槽[2]---后台SOCKET
- Qt汉字得到汉字拼音首字母
- Qt 界面:窗口图标以及任务栏图标的设置
- Gtk与Qt编译环境安装与配置
- Qt中进度条 和进度对话框的典型使用方法
- Qt:解决使用png图片时,报错libpng warning: iCCP: known incorrect sRGB profile的问题
- qt 调试日志安装
- ubuntu 12.04 下搭接Qt 嵌入式开发环境
- VS2010上写QT代码,但是显示不出来QString的值-解决办法
- QT 主窗口和非模态对话框切换 以及消息通信
- QT读写配置文件(.ini)
- QT正则表达式学习(Windows目录禁止九个字符)
- QT中静态库的生成与使用
- 有关eigen库在qt中的使用
- Qt学习之路之浏览器简单操作
- Qt学习之路之启动浏览器
- Qt之QSS中替代background-position的方法。