zoukankan      html  css  js  c++  java
  • 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 
    ",_dso_file.c_str());
    62         destroyer(_instance); //free your dynamic library
    63     }
    64     if(_handle)
    65     {
    66         printf("GLY_Plugin Free the handle  %s 
    ",_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 
    ");
        }
        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
    ");
        return Message_Plugin::plugin_create();  // for our plugin system
    }
    
    void plugin_destroy(void *plugin)
    {
        printf("plugin unloading
    ");
        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
  • 相关阅读:
    一些业内有名的网站收集
    WCF重载
    FCKEditor fckconfig.js配置,添加字体和大小 附:中文字体乱码问题解决
    查询第几条到第几条的数据的SQL语句
    SPOJ 9939 Eliminate the Conflict
    UVA 10534 Wavio Sequence
    HDU 3474 Necklace
    POJ 2823 Sliding Window
    UVA 437 The Tower of Babylon
    UVA 825 Walking on the Safe Side
  • 原文地址:https://www.cnblogs.com/gearslogy/p/5478646.html
Copyright © 2011-2022 走看看