一個軟件,若是把全部的功能寫進C++源碼,維護,擴展,編譯都特別麻煩。ios
共享庫後綴名。Linux -> .so Windows -> .dllapi
關於動態符號顯示問題,具體能夠看系統的API,如今作了個只支持Linux.ide
Linux 查看一個動態庫的符號 nm -D plugin.so函數
注意Linux若是不設置符號隱藏,那麼默認的動態庫全部的符號都是暴露的。能夠用下面的語句設置符號是可暴露。this
#define TopVertexAPI __attribute__ ((visibility("default")))spa
爲何不讀取C++類的符號,由於每一個編譯器編譯C++的函數符號都是不同,因此將要暴露的符號所有定義爲C符號,插件
C符號不會被修飾。好作跨平臺。關鍵字:extern "C"設計
設計方法:GLY_Plugin.h 主要管理插件讀取,插件釋放內存,查找符號。3d
GLY_MessagePluginAPI.h 主要是純虛類,提供給用戶的APIcode
GLY_PluginRegister.h 主要是作符號顯示隱藏
1 // 2 // Created by gearslogy on 5/9/16. 3 // 4 5 #ifndef API_DESIGN_GLY_PLUGIN_H 6 #define API_DESIGN_GLY_PLUGIN_H 7 8 #include <string> 9 class GLY_Plugin 10 { 11 public: 12 GLY_Plugin(std::string file); 13 ~GLY_Plugin(); 14 void *operator->(); 15 void *getPlugin(); 16 private: 17 std::string _dso_file; 18 void *_handle; 19 20 //a pointer to a function can point to -> void * plugin_creator () 21 typedef void* (*plugin_creator)(); 22 23 // now create point can point any like -> void * plugin_creator () 24 plugin_creator creator; 25 26 // 27 typedef void (*plugin_destroy)(void *); 28 plugin_destroy destroyer; 29 30 //plugin instance ,instance is a class handle 31 void *_instance; 32 }; 33 34 35 #endif //API_DESIGN_GLY_PLUGIN_H
1 // 2 // Created by gearslogy on 5/9/16. 3 // 4 #ifdef __GNUC__ 5 #include <dlfcn.h> 6 #endif 7 #include "GLY_Plugin.h" 8 #include <stdio.h> 9 10 11 GLY_Plugin::GLY_Plugin(std::string file) 12 { 13 14 15 _dso_file = file; 16 _handle = NULL; 17 _instance = NULL; 18 19 20 // LINUX platform 21 #ifdef __GNUC__ 22 _handle = dlopen(_dso_file.c_str(),RTLD_LAZY); 23 if(!_handle) 24 { 25 std::string so_open_error = file + " open error "; 26 throw so_open_error; 27 } 28 29 30 //@creator() function return a pointers to the C++ class(_instance) 31 creator = (plugin_creator)dlsym(_handle,"plugin_create"); // search the signal plugin_create 32 if(creator == NULL) 33 { 34 dlclose(_handle); 35 throw "plugin creator not found "; 36 } 37 destroyer = (plugin_destroy)dlsym(_handle, "plugin_destroy"); 38 if(destroyer == NULL) 39 { 40 dlclose(_handle); 41 throw "plugin destroyer not found"; 42 } 43 44 try 45 { 46 _instance = creator(); 47 } 48 catch (...) 49 { 50 dlclose(_handle); 51 _handle= NULL; 52 throw std::exception(); 53 } 54 #endif 55 56 } 57 GLY_Plugin::~GLY_Plugin() 58 { 59 if(_instance) 60 { 61 printf("GLY_Plugin Free the instance %s \n",_dso_file.c_str()); 62 destroyer(_instance); //free your dynamic library 63 } 64 if(_handle) 65 { 66 printf("GLY_Plugin Free the handle %s \n",_dso_file.c_str()); 67 dlclose(_handle); // close the dynamic.so 68 } 69 } 70 void *GLY_Plugin::operator->() 71 { 72 return _instance; 73 } 74 void *GLY_Plugin::getPlugin() 75 { 76 return _instance; 77 }
1 // 2 // Created by gearslogy on 5/9/16. 3 // 4 5 #ifndef API_DESIGN_GLY_MESSAGEPLUGINAPI_H 6 #define API_DESIGN_GLY_MESSAGEPLUGINAPI_H 7 8 9 10 11 class MessagePlugin_interface 12 { 13 public: 14 MessagePlugin_interface(){}; 15 virtual void cookMyMessage()=0; 16 virtual ~MessagePlugin_interface(){}; 17 18 }; 19 20 21 #endif //API_DESIGN_GLY_MESSAGEPLUGINAPI_H
1 // 2 // Created by gearslogy on 5/10/16. 3 // 4 5 #ifndef API_DESIGN_GLY_PLUGINREGISTER_H 6 #define API_DESIGN_GLY_PLUGINREGISTER_H 7 8 #ifdef _WIN32 9 #define TopVertexAPI __declspec(dllexport) 10 #else 11 #define TopVertexAPI __attribute__ ((visibility("default"))) 12 #endif 13 14 #define TopVertexHiddenAPI __attribute__((visibility("hidden"))) 15 16 17 18 // do not use C++ function style. 19 extern "C" TopVertexAPI void *plugin_create(); 20 extern "C" TopVertexAPI void plugin_destroy(void *); 21 22 23 #endif //API_DESIGN_GLY_PLUGINREGISTER_H
主程序:
#include <iostream> #include "GLY_Plugin.h" #include "GLY_MessagePluginAPI.h" using namespace std; int main() { GLY_Plugin MessagePlugin_dyn("./libapi_plugin.so"); MessagePlugin_interface *message_plugin_handle = (MessagePlugin_interface*) (MessagePlugin_dyn.getPlugin()); message_plugin_handle->cookMyMessage(); return 0; }
製做一個插件
#include <GLY_MessagePluginAPI.h> #include <stdio.h> #include <GLY_PluginRegister.h> class Message_Plugin:public MessagePlugin_interface { public: Message_Plugin() { } void cookMyMessage() { printf("MessagePlugin cookMyMessage Houdini function \n"); } static Message_Plugin * plugin_create() { return new Message_Plugin; // create the class pointer } static void *plugin_destroy(Message_Plugin *plugin) { delete plugin; } virtual ~Message_Plugin() { } }; void *plugin_create() { printf("plugin loading\n"); return Message_Plugin::plugin_create(); // for our plugin system } void plugin_destroy(void *plugin) { printf("plugin unloading\n"); Message_Plugin::plugin_destroy((Message_Plugin*) plugin ); }
主程序運行結果:
plugin loading
MessagePlugin cookMyMessage Houdini function
GLY_Plugin Free the instance ./libapi_plugin.so
plugin unloading
GLY_Plugin Free the handle ./libapi_plugin.so
GCC對一些屬性的定義:
#if defined _WIN32 || defined __CYGWIN__ #ifdef BUILDING_DLL #ifdef __GNUC__ #define DLL_PUBLIC __attribute__ ((dllexport)) #else #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. #endif #else #ifdef __GNUC__ #define DLL_PUBLIC __attribute__ ((dllimport)) #else #define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. #endif #endif #define DLL_LOCAL #else #if __GNUC__ >= 4 #define DLL_PUBLIC __attribute__ ((visibility ("default"))) #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define DLL_PUBLIC #define DLL_LOCAL #endif #endif