Write Your software base on plugin(C/C++ ABI)

一個軟件,若是把全部的功能寫進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
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 }
GLY_Plugin.cpp

 

 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
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
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
相關文章
相關標籤/搜索