扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
-lxx
员工经过长期磨合与沉淀,具备了协作精神,得以通过团队的力量开发出优质的产品。成都创新互联坚持“专注、创新、易用”的产品理念,因为“专注所以专业、创新互联网站所以易用所以简单”。公司专注于为企业提供网站设计、做网站、微信公众号开发、电商网站开发,成都小程序开发,软件按需求定制开发等一站式互联网企业服务。
xx是你的.so文件名
其实使用方法和你使用数学库函数是一样的,源代码中添加
#include math.h,编译的时候,加上-lm参数。
注:linux下的.so文件为共享库,相当于windows下的dll文件。
扩展资料:
linux下编写调用so文件实例
.so是Linux(Unix)下的动态链接库. 和.dll类似.
比如:
文件有: a.c, b.c, c.c
gcc -c a.c
gcc -c b.c
gcc -c c.c
gcc -shared libXXX.so a.o b.o c.o
要使用的话也很简单. 比如编译d.c, 使用到libXXX.so中的函数, libXXX.so地址是MYPATH
gcc d.c -o d -LMYPATH -lXXX
注意不是-llibXXX
test.c文件和一个test.h,这两个文件要生成libsotest.so文件。然后我还有一个testso.c文件,在这个文件里面调用libsotest.so中的函数。
编写的过程中,首先是编译so文件,我没有编写makefile文件,而是参考的2里面说的直接写的gcc命令。
因为so文件里面没有main函数,所以是不可执行的,所以编译的时候要加上-c,只生成目标文件。
相关接口:
#include dlfcn.hvoid *dlopen(const char *filename, int flag);char *dlerror(void);void *dlsym(void *handle, const char *symbol);int dlclose(void *handle);123456789
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}#endif123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
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#endif1234567891011121314151617181920212223242526
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.hint show1(char *src)
{ printf("%s\n", src); return 100;
}int show2(int *x)
{ printf("%2d\n", *x); return 101;
}12345678910111213141516171819202122232425262728293031
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.hextern "C" int show1(char *src)
{ printf("%s\n", src); return 100;
}extern "C" int show2(int *x)
{ printf("%2d\n", *x); return 101;
}12345678910111213141516171819202122232425262728293031
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;
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
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
123456
引用:
百度 dlopen(3) - Linux man page
错误:
未找到符合
该函数的定义没有链接进.so文件中时,在链接时加上-Wl,-z -Wl,defs参数,可以避免这个问题
根据相应的头文件、和链接使用的库文件,编译链接后,即是可以使用该.so文件了
~~~~~~~
假设在linux上用gcc编译程序,需要用下列编译选项生成.so文件:
gcc -fPIC -shared
.so 文件安装一般是在/usr/lib或者/usr/local/lib下,安装后不需要绝对路径即可使用。当然你也可以安装到工程文件夹下面,不过很少有这么做的。使用时只需要dlopen()函数打开这个库,用dlsym()函数将动态库的函数体加载进来;同样已加载的动态函数库可以用dlclose()关闭。
详细使用方法百度搜dlopen 即可。
linux下的.so文件为共享库,相当于windows下的dll文件,使用方法如下:
在你的工程源代码里包含.h头文件,然后可以调用动态库里的函数,在链接的时候加上如下编译器参数:
-l xx.so
如果你的so文件是以lib开头的,还可以直接这样使用:
-lxx
xx是你的.so文件名
其实使用方法和你使用数学库函数是一样的,源代码中添加
#include math.h,编译的时候,加上-lm参数。
C++编译so文件与C编译so一样都是加参数 -shared
C语言调用C++的so
首先C要调用的C++的函数必须是extern "C"声明的。
其次编译C程序时需要增加链接libstdc++.so(可能名字不打对自己查查)
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流