• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            codeArt

            codeArt

            QT中的插件

             

            QT有著獨(dú)特的插件管理方法便于使用,調(diào)理清晰.完全可以替代WIN32下的動(dòng)態(tài)庫(kù),靜態(tài)庫(kù).不過(guò),QT也支持動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)加載 .見(jiàn)QLibrary,最終,QLibrary調(diào)用WIN32下的LoadLibrary,GetProcAddress函數(shù).


            Qt插件的使用方法:

            [1]project_main_1工程中定義接口

            class interface__1
            {
            public:
                
            void __func1() = 0;
                
            void __func2() = 0;
                
            void __func3() = 0;
            }
            ;
                
            class interface__2
            {
            public:
                
            void __func4() = 0;
                
            void __func5() = 0;
                
            void __func6() = 0;
            }
            ;

            [2]project_plugin_1工程中實(shí)現(xiàn)接口

            class derive__1:public interface__1,interface__2
            {
            public:
                
            void __func1();
                
            void __func2();
                
            void __func3();
                
            void __func4();
                
            void __func5();
                
            void __func6();
            }
            ;

            [3]project_main_1中使用QPluginLoader,QPluginLoader內(nèi)部實(shí)現(xiàn)也是使用LoadLibrary,GetProcAddress,稍后會(huì)有說(shuō)明

            用法1:

            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]);    
            }

            用法2:

            QpluginLoader pl(“plugin path”);
            Qobject
            * plugin = pl.instance();

            這里可以看出,充分的使用了對(duì)象對(duì)象的多態(tài).那么,QpluginLoader是如何實(shí)現(xiàn)的呢?

            看下面細(xì)節(jié).

            Qt的類幾乎所有的都有一個(gè)QT_class+private的類,用來(lái)實(shí)現(xiàn)具體邏輯,暴露給我們的類定義通用的接口.QpluginLoader的內(nèi)部類是QLibraryPrivate,QLibrary是同一個(gè).

            [1]如何加載

            bool QLibraryPrivate::loadPlugin()
            {
                
            if (instance) {
                    libraryUnloadCount.
            ref();
                    
            return true;
                }

                
            if (load()) {//這里最終調(diào)用load_sys()
                    instance =    (QtPluginInstanceFunction)resolve("qt_plugin_instance");//注意這里的 qt_plugin_instance,插件里面必然導(dǎo)出該函數(shù)名稱
                    return instance;
                }

                
            return false;
            }


            bool QLibraryPrivate::load_sys()
            {
            #ifdef Q_OS_WINCE
                QString attempt 
            = QFileInfo(fileName).absoluteFilePath();
            #else
                QString attempt 
            = fileName;
            #endif

                
            //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 
            = realfilename;
                    
            else
                        qualifiedFileName 
            = dir.filePath(realfilename);
                }

                
            return (pHnd != 0);
            }

            [2] qt_plugin_instance是定義導(dǎo)出的呢?

            在實(shí)現(xiàn)接口時(shí),必須加上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_data; } \
                        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)> _instance; \
                        
            if (!_instance)      \
                            _instance 
            = new IMPLEMENTATION; \
                        
            return _instance; \
                    }
            去掉宏之后,是2個(gè)函數(shù).
            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_data;
            }


            extern __declspec(dllexport) QObject* qt_plugin_instance()
            {
                Qpoint
            <QOjbect> _instance;
                
            if (!_instance)
                            _instance 
            = new PLUGINCLASS;
                        
            return _instance;
            }

            [3] instancetypedef QObject *(*QtPluginInstanceFunction)();


            這樣就實(shí)現(xiàn)了QT的插件.但是還沒(méi)完.

            在定義接口時(shí),還應(yīng)加上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

            posted on 2010-08-28 19:56 codeArt 閱讀(5722) 評(píng)論(0)  編輯 收藏 引用 所屬分類: QT


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            <2010年8月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            文章檔案

            編程與開(kāi)源

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            欧美性大战久久久久久 | 久久99国产亚洲高清观看首页 | 伊人久久大香线蕉AV一区二区| 久久午夜福利电影| 久久精品国产男包| 久久99精品国产一区二区三区| 精品欧美一区二区三区久久久| 久久久久久久综合狠狠综合| 久久久久久午夜成人影院 | 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 亚洲国产成人久久综合区| 久久久久久久波多野结衣高潮| 成人国内精品久久久久影院| 久久久久国产成人精品亚洲午夜| 久久天天躁狠狠躁夜夜躁2014| 漂亮人妻被黑人久久精品| 久久亚洲精品无码播放| 国产精品国色综合久久| 亚洲欧美成人久久综合中文网| 久久精品男人影院| 少妇精品久久久一区二区三区| 精品国产一区二区三区久久蜜臀 | 久久国产亚洲精品麻豆| 久久久国产亚洲精品| 国内精品久久久久久久久| 久久人人爽人人爽人人片av高请| 久久男人中文字幕资源站| 97久久超碰国产精品2021| 婷婷综合久久中文字幕蜜桃三电影 | 青青国产成人久久91网| 久久丫精品国产亚洲av不卡| 国产精品亚洲综合久久| 久久精品?ⅴ无码中文字幕| 天天综合久久久网| 国产欧美久久久精品| 国产精品久久久久久一区二区三区| 狠狠色婷婷久久一区二区| 久久人人爽人人爽人人爽 | 久久国产乱子伦精品免费午夜| 7777久久亚洲中文字幕| 久久国产精品-久久精品|