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 主要是做符号显示隐藏
//
// 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)的更多相关文章
- A Study of WebRTC Security
转自:http://webrtc-security.github.io/ A Study of WebRTC Security Abstract Web Real-Time Communication ...
- What Can Java Technology Do?
What Can Java Technology Do? The general-purpose(多用途的), high-level Java programming language is a po ...
- JDK版本不兼容问题之:一台机器安装多个版本的JDK
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://guojie.blog.51cto.com/59049/45964 我的机器上最开 ...
- JAVA学习提高之----安装多个JDK版本的问题
我的机器上最开始安装的是jdk1.6,后来因为工作需要又安装了jdk1.4.但是,环境变量我并未更改,还是指向jdk1.6的路径的.可是,在cmd窗口输入 Java -version 却得到是1.4. ...
- 【转】使用BBB的device tree和cape(重新整理版)
只要你想用BBB做哪怕一丁点涉及到硬件的东西,你就不可避免地要用到cape和device tree的知识.所以尽管它们看起来很陌生而且有点复杂,但还是得学.其实用起来不难的.下面我只讲使用时必须会的内 ...
- 【转】用Device tree overlay掌控Beaglebone Black的硬件资源
原文网址:https://techfantastic.wordpress.com/2013/11/15/beaglebone-black-device-tree-overlay/ 经过一晚上的Goog ...
- 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 ...
- NSIS皮肤插件
原文 NSIS皮肤插件 [有一个更好的皮肤,大家不妨试一下.http://www.flighty.cn/html/bushu/20110413_118.html ] 对于一般的安装不推荐使用皮肤,因为 ...
- mybatis枚举映射成tinyint
第一步:定义顶级枚举接口 public interface BaseEnum<E extends Enum<?>, T> { public T getCode(); publi ...
随机推荐
- Yii源码阅读笔记(三十三)
ServiceLocator,服务定位类,用于yii2中的依赖注入,通过以ID为索引的方式缓存服务或则组件的实例来定位服务或者组件: namespace yii\di; use Yii; use Cl ...
- java线程同步 以及wait 和notify用法
package test; public class ThreadTest2 extends Thread { private int threadNo; private String lock; p ...
- Linq分组
1.lin语句 int[] nums = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 3 }; DataTable table = new DataTable("Numb ...
- 转一个PDevMode格式属性说明...
找不到原始来源了... //PDevMode = _devicemodeW; // _devicemodeW = record // dmDeviceName: array[0..CCHDEVICEN ...
- 五子棋AI清月连珠开源
经过差不多两年的业余时间学习和编写,最近把清月连珠的无禁手部分完善得差不多了.这中间进行了很多思考,也有很多错误认识,到现在有一些东西还没有全面掌握,所以想通过开源于大家共同交流. 最近一直发表一些五 ...
- SQL的四种连接-左外连接、右外连接、内连接、全连接
今天在看一个遗留系统的数据表的时候发现平时查找的视图是FULL OUT JOIN的,导致平时的数据记录要进行一些限制性处理,其实也可以设置视图各表为右外连接并在视图上设置各列的排序和筛选条件就可以达到 ...
- Hibernate 异常提示_1
INFO: HHH000041: Configured SessionFactory: null九月 15, 2016 12:29:35 上午 org.hibernate.engine.jdbc.co ...
- 5.首次登陆与在线求助man page
X Window与命令行模式的切换:通常我们也称命令行模式为终端界面(terminal或console),linux默认的情况下会提供6个Terminal来让用户登录,切换的方式为使用[Ctrl]+[ ...
- php代码性能分析方法
1.用到的函数 microtime() ,函数返回当前 Unix 时间戳和微秒数,本函数以 "msec sec" 的格式返回一个字符串,其中 sec 是自 Unix 纪元(0:00 ...
- 使用CLion编辑C工程
最近正在研究Linux C代码编辑器,确实也不太喜欢SI(Windows看代码还行,编辑一般,同步麻烦), 尝试使用CLion,但对makefile工程支持不好,怎么编译还没搞懂, 阅读.编辑还不错, ...