c语言插件实现原理,C语言实现插件机制

现在越来越多的软件项目都提供插件机制,这样使得软件的扩展性大大增强,那么到底插件机制的实现是怎么样的呢?在这里只谈论C语言的实现,其实C语言实现插件的例子也很多,像mjpg-streamer就是将输入输出做成插件,dm500机顶盒的主程序enigma也使用了插件机制,我就是从enigma当中学习的。好了,这里给一个简单的例子来看看如何实现。

我的设想是这样的:有一个主程序,有一个插件(.so文件),主程序里面提供一些最基本的功能模块,而在插件中使用这些功能模块实现某些功能。简单点就是主程序要调用.so文件中的函数,而.so要调用主程序中的某些基础函数。

为了既能使用插件a.so, 又能使用插件b.so, 还能使用插件c.so,这里要显式调用动态链接库,即通过dlopen, dlsym, dlclose来使用.so文件,还是直接来看代码。

#mkdir soplugin

#cd soplugin

#vim main.h

//main.h

#ifndef MAIN_H

#define MAIN_H

class A {

public:

A(){};

~A(){};

void p(const char *s);

};

#endif

#vim main.cpp

#include

#include   // dlopen/dlsym/dlclose头文件

#include "main.h"

void A::p(const char *s)

{

printf("A::p()\n");

}

void plugin_show(const char *s)  // 这个函数会被.so文件调用

{

printf("%s\n", s);

}

int main(int argc, char *argv[])

{

int (*PluginExec)(int argc, char *argv);

void *plugin;

printf("loading...\n");

plugin = dlopen("./tplugin.so", RTLD_GLOBAL|RTLD_NOW); // 显式打开.so文件

if (plugin == NULL) {

printf("ptr: %p\n", plugin);

perror("Can not load tplugin.so");

return -1;

}

PluginExec = (int (*)(int, char*))dlsym(plugin, "plugin_exec"); // 得到入口函数指针

if (PluginExec) {

PluginExec(0, NULL);  // 调用入口函数

}

dlclose(plugin);

return 0;

}

#vim plugin.cpp

#include "main.h"

extern void plugin_show(const char *s);

extern "C"

int plugin_exec(int argc, char *argv[])  // 这里要用extern "C"声明,否则C++编译器会给函数名加上一些乱七八糟的东西,不信你可以试试,然后用objdump去查查看

{

A a;

a.p("in plugin_exec"); // 这个在主程序中实现

plugin_show("in plugin.");  // 这个也在主程序中实现

return 0;

}

好了,代码就这些,很简单,但能说明问题就行了,再写个Makefile。

# vim Makefile

all:

g++ -shared -fPIC -DPIC -c plugin.cpp -I.

ld -shared -o tplugin.so plugin.o

g++ -Wl,-E -o mm main.cpp -ldl

前面两行是将plugin.cpp做成一个.so文件,后面一行是编绎main.cpp,这里要特别注意参数-Wl,-E,这个参数意思是将-E参数传递给链接器ld,最终的目的是将main.cpp中的函数输出成全局符号,以方便.so文件调用,如果没有此参数,那么编绎也不会有问题,但在运行时dlopen总是会失败,原因是无法解决符号依赖问题。关于这个参数你可以用objdump对比一下加与不加的结果差别。

好了,接下来编译然后运行。

#make

g++ -shared -fPIC -DPIC -c plugin.cpp -I.

ld -shared -o tplugin.so plugin.o

g++ -Wl,-E -o mm main.cpp -ldl

#./mm

loading...

A::p()

in plugin.

这个例子只是简单的实现打印,但至少已经可以看到主程序和.so文件之间可以调用了,那我再实现a.so, b.so当然也不成问题了。可能有人会产生疑问,为什么不隐式调用呢?原因是:如果隐式调用就必须在编译阶段确定好.so文件,这样就谈不上可扩展插件了,它们之间就存在了编译上的依赖关系。而显式调用是在运行期间确定他们的依赖关系的。

如果有兴趣可以参数mjpg-streamer去学习,但是mjpg-streamer中的插件没有调用主程序的函数,最好的学习例子还是enigma,他里面实现了大量的插件。以后嵌入式软件项目的扩展性要求会越来越高,插件扩展也大受欢迎,插件扩展的机制很多,需要我们去收集学习,这里讲的是最简单的一种。我为什么要学习,原因是我目前参与的一个项目主程序尽然大到30多MB,编译链接时间太长,要扩展功能就更痛苦了,一次一次的编译/链接,一次一次的等待,真是折磨。

附:

enigma是dm500机顶盒的主程序,enigma本身通过c++实现gui, gdi, dvb等一堆基础库,并实现了插件管理器,外围的功能基本全是c/c++插件实现。

enigma2是dm800的机顶盒主程序,enigma2就比enigma更高级了,他通过c++实现gui, gdi, dvb等一些基础库,其余的界面功能,机顶盒功能全部是用动态语言python实现,中间使用swig胶合在一起。也是不错的学习例子,但项目太大,学习不太容易。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/417613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql 简单加密函数

用到了之前的数字转换为16进制数函数 IntToHex create function [dbo].[IntToHex](num int)returns varchar(100)asbegindeclare re varchar(100)set rewhile num>0select resubstring(0123456789ABCDEF,num%161,1)re,numnum/16return(re)endcreate function [dbo].[GetUser…

最全面的Android Studio使用教程【申明:来源于网络】

最全面的Android Studio使用教程【申明:来源于网络】 http://www.admin10000.com/document/5496.html 转载于:https://www.cnblogs.com/yearHeaven/p/6741388.html

linkedhashmap 顺序_LinkedHashMap 源码详细分析(JDK1.8)

1. 概述LinkedHashMap 继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题。除此之外,LinkedHashMap 对访问顺序也提供了相关支持。在一些场景下,该特性…

testNG入门详解

TestNG 的注释: DataProvider ExpectedExceptions Factory Test Parameters <suite name"ParametersTest"><test name"Regression1"><classes><class name"com.example.ParameterSample" /><class name"com.exa…

尼康相机报错err_数码相机遇到这12种错误,自己动手就能解决,再不用找人维修...

如果您资深摄影师或者专业摄影爱好者&#xff0c;那么您必须熟悉下面提到的数码相机所出现的问题和错误。如果您没有遇到任何问题&#xff0c;要么您是初学者&#xff0c;要么您已经很少拍摄了。下面列出的常见相机问题及其解决方案&#xff0c;会为您在使用数码相机的过程中提…

c语言 申请1k内存,怎么解决函数内申请内存,函数外释放的问题

由于不同的编译器和库&#xff0c;其内部关于内存申请释放的实现不同&#xff0c;因此不能直接要求用户指定用某个函数释放内存&#xff0c;必须要单独自己封装一个释放的接口。有两种思路&#xff1a;一是以指针作为参数得到数组地址&#xff0c;单独设计一个释放的函数&#…

SQL Server CLR 启用、部署

sqlserver启用CLRexec sp_configure clr enabled,1 --1,启用clr 0,禁用clrRECONFIGURESQL Server CLR 部署到某个数据库后&#xff0c;便成为那个数据库的一部分&#xff0c;即便备份及还原到其它机器上&#xff0c;它依然具有CLR带来的功能。SqlString 数据类型转换成 nvarcha…

mysql 慢查询过多_MySQL 慢查询优化

为什么查询速度会慢1.慢是指一个查询的响应时间长。一个查询的过程&#xff1a;客户端发送一条查询给服务器服务器端先检查查询缓存&#xff0c;如果命中了缓存&#xff0c;则立可返回存储在缓存中的结果。否则进入下一个阶段服务器端进行SQL解析、预处理&#xff0c;再由优化器…

sqlserver获得到当前游标中存在的数据行数

Select CURSOR_ROWS 可以得到当前游标中存在的数据行数。 注意&#xff1a;此变量为一个连接上的全局变量&#xff0c;因此只对应最后一次打开的游标。

android beta项目官方页面,安卓7.0开发者预览版如何安装?Android Beta项目正式上线...

谷歌现在越来越不按常理出牌了&#xff0c;今天早些时候&#xff0c;他们已经提前秀出了Android 7.0。从最新亮相的Android N开发者预览版来看&#xff0c;谷歌进行了一些调整&#xff0c;但更重要的是&#xff0c;增加了一些新的功能&#xff0c;比如分屏、新的通知控制等。那…

iOS-模糊查询

http://blog.csdn.net/qq_33701006/article/details/51836914 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 目录(?)[] 前言: 为了巩固FMDB,就来找个简单的Demo学习一下。不好找工作啊&#xff0c;就学习吧&#xff0c;没应聘的消遣吧。 简单介…

嵌入式操作系统一览

其实&#xff0c;嵌入式系统并不是一个新生的事物&#xff0c;从八十年代起&#xff0c;国际上就有一些IT组织、公司&#xff0c;开始进行商用嵌入式系统和专用操作系统的研发。这其中涌现了一些著名的嵌入式系统&#xff1a; Windows CEMicrosoft Windows CE是从整体上为有限资…

connect跨进程 qt_编写 Qt 跨线程异步调用器

本文使用 Zhihu On VSCode 创作并发布本文使用 CC BY-NC-SA 4.0 许可协议&#xff0c;转载请注明来源一、设计背景众所周知&#xff0c;Qt 的信号槽系统提供了线程安全的跨线程异步执行代码的机制(Qt::QueuedConnection)。使用该机制&#xff0c;可以让槽函数代码在另一个线程执…

Web开发入门疑问收集(不定期更新)

bootstrap container和container-fluid的区别 原始链接 container根据显示设备满足的最小宽度&#xff0c;来决定实际内容宽度&#xff0c;是一个根据设置内容阶梯式响应的布局。例子&#xff1a;media (min-width: 568px) {.container {width: 550px;} } media (min-width: 99…

钱币掉落动画android,mpvue实现小程序签到金币掉落动画(api实现)

这里使用小程序自带的api来实现&#xff0c;用小程序来写动画的恶心点在于&#xff0c;没有帧&#xff0c;只能用setimeout 来作为帧来使用&#xff0c;下面是实现代码&#xff0c; 下面是简单用div代替了图片&#xff0c;需要什么图片&#xff0c;可以自行替换相应的div即可需…

前端学习(2197):__WEBPACK_IMPORTED_MODULE_1_vuex__.a.store is not a constructor

在使用vuex过程中&#xff0c;发现报错 typeError:__WEBPACK_IMPORTED_MODULE_1_vuex__.a.store is not a constructor 经查找发现是实例化时 .store用的小写造成的,如下 new Vuex.store({state:{},mutations:{},actions:{},modules:{} }) 实际应为大写!&#xff08;居然有和…

c常见错误

///Segmentation fault段错误可能有未初始化的变量导致段错误的几种情况1、 引用一个包含非法值的指针&#xff08;当然包括空指针&#xff09;。2、 未得到正确的权限的时候进行访问&#xff0c;例如往只读的内存地址写数据。3、 内存越界&#xff08;数组越界&#xff0c;变量…

python学多久能写东西的软件有哪些_怎么自学python,大概要多久?

看完这些还不会算我输1、一小时Python 基础和编码规范鹅厂员工学习Python总结的教程&#xff0c;可用于快速了解Python&#xff0c;适合有其它语言编程基础的同学看&#xff0c;一个小时带你玩转Python2、400全集Python全套视频教程此套视频信息量非常大&#xff0c;我画了个思…

接口测试之HTTP协议详解

引言 HTTP是一个属于应用层的面向对象的协议&#xff0c;由于其简捷、快速的方式&#xff0c;适用于分布式超媒体信息系统。它于1990年提出&#xff0c;经过几年的使用与发展&#xff0c;得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版&#xff0c;HTTP/1.1的规范…