• 3693阅读
  • 0回复

工业自动化软件设计 之四 插件实现 [复制链接]

上一主题 下一主题
离线myer
 

只看楼主 倒序阅读 楼主  发表于: 2011-12-02
Qt的插件使用起来非常简单,但是如果在某些平台上,并不想用Qt库,则需要自己实现类似的功能
以下是一个简单的实现:3个宏
1、实现插件:
     定义插件类的文件
     class IPlugin{...}
     实现:class IPluginImpl : public IPlugin{...}
     在头文件里声明:Pan_Declare_Plugin(IPlugin)
     在实现文件里:Pan_Export_Plugin(IPlugin, IPluginImpl )
2、load插件:
     在需要load的地方,
PanLoadPlugin(IPlugin)
,声明一个loadIPlugin函数
     IPlugin*ipulin = loadIPlugin(filename);

3、代码:
宏定义
  1. #define Pan_Declare_Plugin(baseclass) extern "C"{\
  2. PAN_EXPORTS baseclass *create_##baseclass();};
  3. #define Pan_Export_Plugin(baseclass, implclass) extern "C"{\
  4.     baseclass *create_##baseclass(){return new implclass;}};
panlibrary.h
  1. #pragma once
  2. #ifdef _WIN32
  3. #include <Windows.h>
  4. #include <iostream>
  5. #endif
  6. class PanLibrary
  7. {
  8. public:
  9.     PanLibrary();
  10.     ~PanLibrary();
  11. #ifdef _WIN32
  12.     typedef FARPROC symbol_type;
  13. #else
  14.     typedef void* symbol_type;
  15. #endif
  16.     symbol_type loadEntryPoint(const std::string&);
  17.     bool load(const std::string&);
  18.     symbol_type getSymbol(const std::string&);
  19.     const std::string& getErrorMessage() const;
  20. private:
  21. #ifdef _WIN32
  22.     HINSTANCE _hnd;
  23. #else
  24.     void* _hnd;
  25. #endif
  26.     std::string _err;
  27. };
  28. #define PanLoadPlugin(baseclass)\
  29.     baseclass *load##baseclass(std::string fn)\
  30. {\
  31.     typedef baseclass *(*FUN)(); \
  32.     PanLibrary lib;\
  33.     PanLibrary::symbol_type ret = lib.loadEntryPoint(fn + ":create_" + #baseclass);\
  34.     if(ret)\
  35.     {\
  36.         FUN f = FUN(ret);\
  37.         return f();\
  38.     }\
  39.     return NULL;\
  40. }
panlibrary.cpp
  1. #include "panlibrary.h"
  2. #ifndef _WIN32
  3. #   include <dlfcn.h>
  4. #endif
  5. #include <assert.h>
  6. PanLibrary::PanLibrary() : _hnd(0)
  7. {
  8. }
  9. PanLibrary::~PanLibrary()
  10. {
  11.     
  12.     /* Closing the library here can cause a crash at program exit if
  13.     * the application holds references to library resources in global
  14.     * or static variables. Instead, we let the process discard the
  15.     * library.
  16.     printf("asdf");
  17.     if(_hnd != 0)
  18.     {
  19.     #ifdef _WIN32
  20.     FreeLibrary(_hnd);
  21.     #else
  22.     dlclose(_hnd);
  23.     #endif
  24.     }
  25.     */
  26. }
  27. PanLibrary::symbol_type
  28. PanLibrary::loadEntryPoint(const std::string& entryPoint)
  29. {
  30.     std::string::size_type colon = entryPoint.rfind(':');
  31.     if(colon == std::string::npos || colon == entryPoint.size() - 1)
  32.     {
  33.         _err = "invalid entry point format.";
  34.         return 0;
  35.     }
  36.     std::string libName = entryPoint.substr(0, colon);
  37.     std::string funcName = entryPoint.substr(colon + 1);
  38.     std::string lib = libName;
  39. #ifdef _WIN32
  40.     lib += ".dll";
  41. #elif defined(__APPLE__)
  42.     lib = "lib" + libName + ".dylib";
  43. #elif defined(__hpux)
  44.     lib = "lib" + libName + ".sl";
  45. #elif defined(_AIX)
  46.     lib = "lib" + libName + ".a(lib" + libName + ".so" + ")";
  47. #else
  48.     lib = "lib" + libName + ".so";
  49. #endif
  50.     if(!load(lib))
  51.     {
  52.         return 0;
  53.     }
  54.     return getSymbol(funcName);
  55. }
  56. bool
  57. PanLibrary::load(const std::string& lib)
  58. {
  59. #ifdef _WIN32
  60.     _hnd = LoadLibraryA(lib.c_str());
  61.     //_hnd = LoadLibraryA("testplugin.dll");
  62. #else
  63.     int flags = RTLD_NOW | RTLD_GLOBAL;
  64. #ifdef _AIX
  65.     flags |= RTLD_MEMBER;
  66. #endif
  67.     _hnd = dlopen(lib.c_str(), flags);
  68.     if(_hnd == 0)
  69.     {
  70.         //
  71.         // Remember the most recent error in _err.
  72.         //
  73.         const char* err = dlerror();
  74.         if(err)
  75.         {
  76.             _err = err;
  77.         }
  78.     }
  79. #endif
  80.     return _hnd != 0;
  81. }
  82. PanLibrary::symbol_type
  83. PanLibrary::getSymbol(const std::string& name)
  84. {
  85.     assert(_hnd != 0);
  86. #ifdef _WIN32
  87. #  ifdef __BCPLUSPLUS__
  88.     std::string newName = "_" + name;
  89.     return GetProcAddress(_hnd, newName.c_str());
  90. #  else
  91.     return GetProcAddress(_hnd, name.c_str());
  92. #  endif
  93. #else
  94.     symbol_type result = dlsym(_hnd, name.c_str());
  95.     if(result == 0)
  96.     {
  97.         //
  98.         // Remember the most recent error in _err.
  99.         //
  100.         const char* err = dlerror();
  101.         if(err)
  102.         {
  103.             _err = err;
  104.         }
  105.     }
  106.     return result;
  107. #endif
  108. }
  109. const std::string& PanLibrary::getErrorMessage() const
  110. {
  111.     return _err;
  112. }



http://user.qzone.qq.com/56430808
快速回复
限100 字节
 
上一个 下一个