python 怎么调用so文件

python 怎么调用so文件,第1张

当需要采用调用c++的程序的时候,需要对原有的数据加一个extern "C"封装一下即可。

采用g++编译的代码也需要的,原因可能是因为c++编译器编译后的二进制so文件嫌猜碧中,对c++的函数进行了重新的命芹举名导致的。

extern "C" {

Foo* Foo_new(){ return new Foo()}

void Foo_bar(Foo* foo){ foo->bar()}

}

以下两个网页又更详细的介绍

http://blog.waterlin.org/articles/using-python-ctypes-to-link-cpp-library.html

http://stackoverflow.com/questions/145270/calling-c-c-from-python

最后需要补充的一个问题是:当我调用so文件的时候,会发生一个有趣的现象:

我把python放到streaming找运行的时候,发现streaming始终查找不到so,但是数据却是被上传到hadoop的对应的work目录下。

后来定位到原因:

是python加载动态库方面是默兆纤认从系统lib库上查找库文件。

我的目录在当前目录下,所以需要从libdy.so变为./libdy.so

本文是在ffmpeg的编译完成的基础上用cmake对ffmpeg的so库进行调用

创建新项目的时候,记得勾选include c++ support,项目中会在main目录下自动创建cpp目录并生成一个现成的cpp文件。

效果如下:

具体在CMakeLists中添加的Cmake命令用法,请参考 这篇文章

需要注意的是CMakelists的位置,CMAKE_SOURCE_DIR就代表CMakeLists所在的路径。我的项目中CMakeLists的路径是与build.gradle同级历差的

Androidstudio最新版好像创建完c++后自动生成的CMakeLists是在cpp目录下的,这个CMakeLists在哪都行,不过千万要记住修改几处调用CMakeLists路径的地方。有以橡烂启下几处:

1、CMakeLists中梁如用到CMAKE_SOURCE_DIR的地方

2、build.gradle中

include/libavcodec/avcodec.h是引用的so库的头文件,需要注意使用extern "C"包裹起来

参考链接:

1、 https://www.cnblogs.com/fnlingnzb-learner/p/7593488.html

2、 https://www.jianshu.com/p/a1fe55d5683b

相关接口:

#include <dlfcn.h>void *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=8printf("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.h>int 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.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

}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=8int retprintf("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

http://tldp.org/HOWTO/C++-dlopen/

错误:

未找到符合

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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/8149157.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-13
下一篇 2023-04-13

发表评论

登录后才能评论

评论列表(0条)

保存