AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

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

一个软件,如果把所有的功能写进C++源码,维护,扩展,编译都特别麻烦。

共享库后缀名。Linux -> .so  Windows -> .dll

关于动态符号显示问题,具体可以看系统的API,现在做了个只支持Linux.

 Linux 查看一个动态库的符号 nm -D plugin.so

 

注意Linux如果不设置符号隐藏,那么默认的动态库所有的符号都是暴露的。可以用下面的语句设置符号是可暴露。

#define TopVertexAPI __attribute__ ((visibility("default")))

 

为什么不读取C++类的符号,因为每个编译器编译C++的函数符号都是不一样,所以将要暴露的符号全部定义为C符号,

C符号不会被修饰。好做跨平台。关键字:extern "C"

 

设计方法:GLY_Plugin.h 主要管理插件读取,插件释放内存,查找符号。

  GLY_MessagePluginAPI.h 主要是纯虚类,提供给用户的API

  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

 

posted on 2016-05-10 17:35  gearslogy  阅读(445)  评论(0编辑  收藏  举报