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

相关接口:

#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 __cplusplus
extern "C" {
#endif


typedef 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 _TEST

int 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 __cplusplus
extern "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参数,可以避免这个问题

转载于:https://my.oschina.net/u/3423525/blog/882239

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值