linux 程序动态调用.so文件中的函数

来源:互联网 发布:seo建站 编辑:程序博客网 时间:2024/06/13 15:56

相关接口:

#include <dlfcn.h>void *dlopen(const char *filename, int flag);char *dlerror(void);void *dlsym(void *handle, const char *symbol);int dlclose(void *handle);

eg:
dlapi.c

/*[root@localhost eg]# gcc main.c -Wl,-rpath=./ -ldl -D_TEST[root@localhost eg]# g++ main.c -Wl,-rpath=./ -ldl -D_TEST*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <dlfcn.h>#ifdef __cplusplusextern "C" {#endiftypedef int (*PCall_func0)();typedef int (*PCall_func1)(void *);typedef int (*PCall_func2)(void *, void *);typedef int (*PCall_func3)(void *, void *, void *);typedef int (*PCall_func4)(void *, void *, void *, void *);int dynamic_call_library_func0(char *libName, char *funcName) {     void *handle;    void *error;    PCall_func0 selffunc=NULL;    int ret;    if(libName == NULL)return -9000;    if(funcName == NULL)return -9001;    //打开动态链接库    handle = dlopen(libName, RTLD_LAZY);    if (!handle) {        printf("%s\n", dlerror());        return -9000;    }    dlerror();    //获取一个函数    selffunc = (PCall_func0)dlsym(handle, funcName);    if ((error = dlerror()) != NULL)  {        fprintf(stderr, "%s\n", error);        return -9001;    }    ret = selffunc();    //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。    dlclose(handle);    return ret;}int dynamic_call_library_func1(char *libName, char *funcName, void *argv1) {     void *handle;    void *error;    PCall_func1 selffunc=NULL;    int ret;    if(libName == NULL)return -9000;    if(funcName == NULL)return -9001;    //打开动态链接库    handle = dlopen(libName, RTLD_LAZY);    if (!handle) {        printf("%s\n", dlerror());        return -9000;    }    dlerror();    //获取一个函数    selffunc = (PCall_func1)dlsym(handle, funcName);    if ((error = dlerror()) != NULL)  {        fprintf(stderr, "%s\n", error);        return -9001;    }    ret = selffunc(argv1);    //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。    dlclose(handle);    return ret;}int dynamic_call_library_func2(char *libName, char *funcName, void *argv1, void *argv2) {     void *handle;    void *error;    PCall_func2 selffunc=NULL;    int ret;    if(libName == NULL)return -9000;    if(funcName == NULL)return -9001;    //打开动态链接库    handle = dlopen(libName, RTLD_LAZY);    if (!handle) {        printf("%s\n", dlerror());        return -9000;    }    dlerror();    //获取一个函数    selffunc = (PCall_func2)dlsym(handle, funcName);    if ((error = dlerror()) != NULL)  {        fprintf(stderr, "%s\n", error);        return -9001;    }    ret = selffunc(argv1, argv2);    //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。    dlclose(handle);    return ret;}int dynamic_call_library_func3(char *libName, char *funcName, void *argv1, void *argv2, void *argv3) {     void *handle;    void *error;    PCall_func3 selffunc=NULL;    int ret;    if(libName == NULL)return -9000;    if(funcName == NULL)return -9001;    //打开动态链接库    handle = dlopen(libName, RTLD_LAZY);    if (!handle) {        printf("%s\n", dlerror());        return -9000;    }    dlerror();    //获取一个函数    selffunc = (PCall_func3)dlsym(handle, funcName);    if ((error = dlerror()) != NULL)  {        fprintf(stderr, "%s\n", error);        return -9001;    }    ret = selffunc(argv1, argv2, argv3);    //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。    dlclose(handle);    return ret;}int dynamic_call_library_func4(char *libName, char *funcName, void *argv1, void *argv2, void *argv3, void *argv4) {     void *handle;    void *error;    PCall_func4 selffunc=NULL;    int ret;    if(libName == NULL)return -9000;    if(funcName == NULL)return -9001;    //打开动态链接库    handle = dlopen(libName, RTLD_LAZY);    if (!handle) {        printf("%s\n", dlerror());        return -9000;    }    dlerror();    //获取一个函数    selffunc = (PCall_func4)dlsym(handle, funcName);    if ((error = dlerror()) != NULL)  {        fprintf(stderr, "%s\n", error);        return -9001;    }    ret = selffunc(argv1, argv2, argv3, argv4);    //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。    dlclose(handle);    return ret;}#ifdef _TESTint main(int rgvs, char **rgva){char buff[]="asdfasdf";int x=8;printf("main gcc build\n");printf("g_path gcc libeggcc.so  char *\n");    dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show1", buff);printf("g_path g++ libegg++.so char *\n");    dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show1", buff);printf("../lib path gcc libeggcc.so char *\n");    dynamic_call_library_func1("libeggcc.so", "show1", buff);printf("../lib path g++ libegg++.so char *\n");    dynamic_call_library_func1("libegg++.so", "show1", buff);printf("g_path gcc libeggcc.so  int\n");    dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show2", &x);printf("g_path g++ libegg++.so int\n");    dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show2", &x);printf("../lib path gcc libeggcc.so int\n");    dynamic_call_library_func1("libeggcc.so", "show2", &x);printf("../lib path g++ libegg++.so int\n");    dynamic_call_library_func1("libegg++.so", "show2", &x);    return 0;}#endif#ifdef __cplusplus}#endif

dlapi.h

#ifndef _DL_API_H#define _DL_API_H#ifdef __cplusplusextern "C" {#endif/*使用g++编译的.so库中,函数前必须添加 exter "C" 函数参数类型为指针,不或以为引用*/int dynamic_call_library_func0(char *libName, char *funcName) ;int dynamic_call_library_func1(char *libName, char *funcName, void *argv1) ;int dynamic_call_library_func2(char *libName, char *funcName, void *argv1, void *argv2) ;int dynamic_call_library_func3(char *libName, char *funcName, void *argv1, void *argv2, void *argv3) ;int dynamic_call_library_func4(char *libName, char *funcName, void *argv1, void *argv2, void *argv3, void *argv4) ;#ifdef __cplusplus}#endif#endif

eg.c

/*[root@localhost eg]# gcc eg.c -fPIC -shared -o libeggcc.so[root@localhost eg]# g++ eg.c -fPIC -shared -o libegg++.so*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int show1(char *src){    printf("%s\n", src);    return 100;}int show2(int *x){    printf("%2d\n", *x);    return 101;}

eg.cpp

/*[root@localhost eg]# gcc eg.c -fPIC -shared -o libeggcc.so[root@localhost eg]# g++ eg.c -fPIC -shared -o libegg++.so*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>extern "C" int show1(char *src){    printf("%s\n", src);    return 100;}extern "C" int show2(int *x){    printf("%2d\n", *x);    return 101;}

main.c

/*[root@localhost eg]# gcc main.c -Wl,-rpath=./ -ldl -D_TEST[root@localhost eg]# g++ main.c -Wl,-rpath=./ -ldl -D_TEST*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <dlfcn.h>#include "dlapi.h"int main(int rgvs, char **rgva){char buff[]="asdfasdf";int x=8;int ret;printf("main gcc build\n");printf("\ng_path gcc libeggcc.so  char *\n");    ret = dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show1", buff);printf("\ng_path g++ libegg++.so char *\n");    dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show1", buff);printf("\ncur lib path gcc libeggcc.so char *\n");    dynamic_call_library_func1("libeggcc.so", "show1", buff);printf("\ncur lib path g++ libegg++.so char *\n");    dynamic_call_library_func1("libegg++.so", "show1", buff);printf("\ng_path gcc libeggcc.so  int\n");    dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show2", &x);printf("\ng_path g++ libegg++.so int\n");    dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show2", &x);printf("\ncur lib path gcc libeggcc.so int\n");    dynamic_call_library_func1("libeggcc.so", "show2", &x);printf("\ncur path g++ libegg++.so int\n");    dynamic_call_library_func1("libegg++.so", "show2", &x);    return 0;}

makefile

all:    gcc eg.c -fPIC -shared -o libeggcc.so    g++ eg.cpp -fPIC -shared -o libegg++.so    gcc dlapi.c -ldl -fPIC -shared -o libdlapi.so    g++ main.c -L. -ldlapi  -Wl,-rpath=./ -Wl,-rpath=./lib 

引用:
百度 dlopen(3) - Linux man page
http://tldp.org/HOWTO/C++-dlopen/

错误:
未找到符合
该函数的定义没有链接进.so文件中时,在链接时加上-Wl,-z -Wl,defs参数,可以避免这个问题

0 0
原创粉丝点击