• 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
  • 相关阅读:
    Android Studio的git功能的使用介绍
    如何用Android Studio同时使用SVN和Git管理项目
    【.NET深呼吸】动态类型(扩充篇)
    【.net深呼吸】动态类型(高级篇)
    【.net深呼吸】动态类型(娱乐篇)
    VS 2015相当不错的功能:C#交互窗口
    计算照片的面积(WPF篇)
    计算照片的面积(UWP篇)
    【Win 10应用开发】把文件嵌入到XML文档
    【.NET深呼吸】基础:自定义类型转换
  • 原文地址:https://www.cnblogs.com/gearslogy/p/5478646.html
Copyright © 2020-2023  润新知