IEC61499 功能块调用C++ 动态程序库的实现(1)

关于动态库

  1. 动态加载库的优点是在程序运行时加载,而且开发主程序的时候不需要include 库的 .h文件。只需要知道函数的调用格式就可以了。
  2. 动态加载库需要使用CPU 的MMU 支持,所以在cortex-M 单片机上通常不能使用动态加载库的机制。
  3. 我关心得是利用动态库技术来实现轻量级动态软件组件(例如IEC61499 功能块)的部署,更新和维护。

为什么关心动态库的动态加载

实现软件组件的远程动态部署和更新。例如在IEC61499 运行时中,如果用户自己开发ST或者C语言的功能块,开发环境通常是export 模块的C++ 源码,需要重新编译运行时才能更新。无法实现远程更新。如果使用docker 容器工具,显然又过于庞大。因此,我尝试使用动态库来实现功能块的远程部署和独立开发。以后另文报告。

测试例子

CSDN 有许多关于linux 动态库的博文,但是许多文章中不是代码有错误,就是文字太多,或者看不明白。最后

参考了:Linux动态库的 静态加载 和 动态加载 的使用 的博文,并且做了部分修改。我的代码在 window10 的ubuntu (WSL2)上调试通过。

首先,编写了两个函数 math.c 和show.c

math.c

  #include<stdio.h>
   
   int add(int a,int b)
   {
      return a+b;
   }

show.c

   #include<stdio.h>
   
   int show(int a)
   {
       printf("两数之和:%d\n",a);
   }

分别进行编译

gcc -fpic -c math.c  -o math.o 
gcc -fpic -c show.c  -o show.o

在目录中出现了math.o和show.o

链接成共享库

gcc -shared math.o show.o -o libmath.so

编写调用共享库的主程序(dmain.c)

#include<stdio.h>
#include<dlfcn.h>
 
typedef int(*PFUNC_CALL)(int,int);
typedef int(*PFUNC_SHOW)(int);        //给函数指针定义一个别名   PFUNC_SHOW = int(*)(int)
 
int main()
{
     printf("Dynamic lib test\n");
    void *handle = dlopen("./libmath.so",RTLD_LAZY);  //加载动态库
        if(handle==NULL)
        {
            printf("dlopen fail:%s\n",dlerror());
            return -1;
        }
    //获取函数地址
    printf("get add function address\n");
    PFUNC_CALL add = (PFUNC_CALL)dlsym(handle,"add");
    if(add==NULL)
    {
        printf("dlsym fail:%s\n",dlerror());
        return -1;
    }
 
  printf("get show function address\n");
   PFUNC_SHOW show = (PFUNC_SHOW)dlsym(handle,"show");           
    if(show==NULL)                                      
    {
        printf("dlsym fail:%s\n",dlerror());
        return -1;
    }
 
    show(add(9,5));
 
    dlclose(handle);
    return 0;
}

编译 dmain

gcc dmain.c   -ldl -o test

运行 ./test

Dynamic lib test
get add function address
get show function address
两数之和:14

使用的主要函数

加载共享库 ---- dlopen

     filename:给路径按照路径加载,给文件名就根据LD_LIBRARY_PATH环境变量去查找

     flag:加载标志

        RTLD_LAZY:延迟加载,什么时候真正使用的时候才加载  

        RTLD_NOW:立即加载

返回值:

    成功返回动态库的句柄,失败返回NULL

获取动态库的的函数地址 ------- dlsym

    handle:动态库的句柄

    symbol:函数名

返回值:

    成功返回函数地址,失败返回NULL

卸载动态库 -------------dlclose

handle:动态库的句柄

获取出错信息 --------- dlerror

返回错误字符串

猜你喜欢

转载自blog.csdn.net/yaojiawan/article/details/108864653