相关接口:
#include
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
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#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参数,可以避免这个问题