一个软件,如果把所有的功能写进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 主要是做符号显示隐藏

 //
// Created by gearslogy on 5/9/16.
// #ifndef API_DESIGN_GLY_PLUGIN_H
#define API_DESIGN_GLY_PLUGIN_H #include <string>
class GLY_Plugin
{
public:
GLY_Plugin(std::string file);
~GLY_Plugin();
void *operator->();
void *getPlugin();
private:
std::string _dso_file;
void *_handle; //a pointer to a function can point to -> void * plugin_creator ()
typedef void* (*plugin_creator)(); // now create point can point any like -> void * plugin_creator ()
plugin_creator creator; //
typedef void (*plugin_destroy)(void *);
plugin_destroy destroyer; //plugin instance ,instance is a class handle
void *_instance;
}; #endif //API_DESIGN_GLY_PLUGIN_H

GLY_Plugin.h

 //
// Created by gearslogy on 5/9/16.
//
#ifdef __GNUC__
#include <dlfcn.h>
#endif
#include "GLY_Plugin.h"
#include <stdio.h> GLY_Plugin::GLY_Plugin(std::string file)
{ _dso_file = file;
_handle = NULL;
_instance = NULL; // LINUX platform
#ifdef __GNUC__
_handle = dlopen(_dso_file.c_str(),RTLD_LAZY);
if(!_handle)
{
std::string so_open_error = file + " open error ";
throw so_open_error;
} //@creator() function return a pointers to the C++ class(_instance)
creator = (plugin_creator)dlsym(_handle,"plugin_create"); // search the signal plugin_create
if(creator == NULL)
{
dlclose(_handle);
throw "plugin creator not found ";
}
destroyer = (plugin_destroy)dlsym(_handle, "plugin_destroy");
if(destroyer == NULL)
{
dlclose(_handle);
throw "plugin destroyer not found";
} try
{
_instance = creator();
}
catch (...)
{
dlclose(_handle);
_handle= NULL;
throw std::exception();
}
#endif }
GLY_Plugin::~GLY_Plugin()
{
if(_instance)
{
printf("GLY_Plugin Free the instance %s \n",_dso_file.c_str());
destroyer(_instance); //free your dynamic library
}
if(_handle)
{
printf("GLY_Plugin Free the handle %s \n",_dso_file.c_str());
dlclose(_handle); // close the dynamic.so
}
}
void *GLY_Plugin::operator->()
{
return _instance;
}
void *GLY_Plugin::getPlugin()
{
return _instance;
}

GLY_Plugin.cpp

 //
// Created by gearslogy on 5/9/16.
// #ifndef API_DESIGN_GLY_MESSAGEPLUGINAPI_H
#define API_DESIGN_GLY_MESSAGEPLUGINAPI_H class MessagePlugin_interface
{
public:
MessagePlugin_interface(){};
virtual void cookMyMessage()=;
virtual ~MessagePlugin_interface(){}; }; #endif //API_DESIGN_GLY_MESSAGEPLUGINAPI_H

GLY_MessagePluginAPI.h

 //
// Created by gearslogy on 5/10/16.
// #ifndef API_DESIGN_GLY_PLUGINREGISTER_H
#define API_DESIGN_GLY_PLUGINREGISTER_H #ifdef _WIN32
#define TopVertexAPI __declspec(dllexport)
#else
#define TopVertexAPI __attribute__ ((visibility("default")))
#endif #define TopVertexHiddenAPI __attribute__((visibility("hidden"))) // do not use C++ function style.
extern "C" TopVertexAPI void *plugin_create();
extern "C" TopVertexAPI void plugin_destroy(void *); #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 ;
}

制作一个插件

#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

Write Your software base on plugin(C/C++ ABI)的更多相关文章

  1. A Study of WebRTC Security

    转自:http://webrtc-security.github.io/ A Study of WebRTC Security Abstract Web Real-Time Communication ...

  2. What Can Java Technology Do?

    What Can Java Technology Do? The general-purpose(多用途的), high-level Java programming language is a po ...

  3. JDK版本不兼容问题之:一台机器安装多个版本的JDK

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://guojie.blog.51cto.com/59049/45964 我的机器上最开 ...

  4. JAVA学习提高之----安装多个JDK版本的问题

    我的机器上最开始安装的是jdk1.6,后来因为工作需要又安装了jdk1.4.但是,环境变量我并未更改,还是指向jdk1.6的路径的.可是,在cmd窗口输入 Java -version 却得到是1.4. ...

  5. 【转】使用BBB的device tree和cape(重新整理版)

    只要你想用BBB做哪怕一丁点涉及到硬件的东西,你就不可避免地要用到cape和device tree的知识.所以尽管它们看起来很陌生而且有点复杂,但还是得学.其实用起来不难的.下面我只讲使用时必须会的内 ...

  6. 【转】用Device tree overlay掌控Beaglebone Black的硬件资源

    原文网址:https://techfantastic.wordpress.com/2013/11/15/beaglebone-black-device-tree-overlay/ 经过一晚上的Goog ...

  7. find-a-jar-file-given-the-class-name

    Save this as findclass.sh (or whatever), put it on your path and make it executable: #!/bin/sh find ...

  8. NSIS皮肤插件

    原文 NSIS皮肤插件 [有一个更好的皮肤,大家不妨试一下.http://www.flighty.cn/html/bushu/20110413_118.html ] 对于一般的安装不推荐使用皮肤,因为 ...

  9. mybatis枚举映射成tinyint

    第一步:定义顶级枚举接口 public interface BaseEnum<E extends Enum<?>, T> { public T getCode(); publi ...

随机推荐

  1. 浮点数 (IEEE-754)

    浮点数又称"实数",一个浮点数包含三个部分 符号位(S) 阶码 有效数字 S:阶码:有效数字 浮点数是由科学二级制来表示的. 三种类型的浮点数: 短浮点数(32bit):  S(b ...

  2. js 函数返回函数

    <script> var aa = function(fn, time, interval){ return function(){ if (typeof(fn) != 'function ...

  3. hibernate学习(9)——日志,一对一,二级缓存

    1.Hibernate中的日志 1  slf4j 核心jar  : slf4j-api-1.6.1.jar .slf4j是日志框架,将其他优秀的日志第三方进行整合. 整合导入jar包 log4j 核心 ...

  4. Unity5和WebGL移植指南的一些总结

    对于手游开发者来说,更新版本往往意味着非常复杂的过程,你需要根据反馈做更新.测试.提交然后等待审核,而由于不需要客户端依赖,页游往往是快速测试游戏版本的最佳途径,很多人可能都知道Unity 5可以再不 ...

  5. 【Git学习笔记】远程仓库

    第一种情景:本地初始化一个Git仓库后,接着又在github上创建了一个Git仓库,现在要让这两个仓库进行远程同步. 1. 关联本地仓库就和远程仓库  $ git remote add origin ...

  6. MyEclipse 快捷键

    MyEclipse 快捷键1(CTRL) Ctrl+1 快速修复Ctrl+D: 删除当前行Ctrl+Q 定位到最后编辑的地方Ctrl+L 定位在某行Ctrl+O 快速显示 OutLineCtrl+T ...

  7. SQL CURSOR

    SET NOCOUNT ON; DECLARE @vendor_id int, @vendor_name nvarchar(50),     @message varchar(80), @produc ...

  8. Intellij Idea 工具在java文件中如何避免 import .*包

    Intellij Idea工具在java文件中怎么避免import java.utils.*这样的导入方式,不推崇导入*这样的做法!Editor->Code Style->Java-> ...

  9. nginx 配置优化(简单)

    配置文件     正常运行的必备配置:         1.user username [groupname]:(推荐nginx)         以那个用户身份运行,以在configure指定的用户 ...

  10. shell中对字符串的处理

    1.替换字符串1为字符串2 sed "s/str1/str2/g" 2.获取字符串中的一部分 例:boke-blade 取得boke:sed -e "s/-.*//g&q ...