100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > python调用C语言动态链接库详解

python调用C语言动态链接库详解

时间:2024-05-17 17:46:11

相关推荐

python调用C语言动态链接库详解

python调用动态链接库详解

Python 调用动态链接库环境说明构建动态链接库python动态链接库基础调用python动态链接库结构体调用python动态链接库回调函数

本文介绍在linux环境下python调用c语言编写的动态链接库so。

Python 调用动态链接库

linux操作系统中动态链接库为so文件。python调用so文件使用动态方式加载,python中使用ctypes库ctypes是Python调用c的动态链接库的一个内置模块。

环境说明

操作系统:linuxpython: python3

构建动态链接库

项目结构

├── CMakeLists.txt # cmake构建配置文件├── # 动态链接库源文件└── hello.h# 动态链接库头文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.1)# 设置cmake最小版本project(hello)# 设置项目名称set(src_h hello.h)# 设置头文件set(src_c hello.c)# 设置源文件add_library( hello SHARED ${src_h} ${src_c})# 生成libhello.so库文件。

hello.h

#ifdef __cplusplusextern "C"{#endif#ifndef _HELLO_H_#define _HELLO_H_// -------------- so基础调用 -------------void say_hello();// 基础调用,无参数调用void say_hello2(int iNum);// 传递int类型参数void say_hello3(const char *str);// 传递char * 字符串int say_hello4(int iNum1,int Num2);// 传递两个参数,并且带返回值。// -------------- so结构体调用 -------------struct POINT{int x;int y;};struct POINT get_mouse_position();// 返回结构体struct POINT *get_position();// 返回结构体指针void release_point(struct POINT * ptrData);// 将结构指针作为参数// -------------- so 回调函数 -------------typedef void (callback)();typedef int (callback2)(int);void send_message(int a, callback funcPtr);// 无参数的回调函数int send_message2(int a, callback2 funcPtr);// 带参数,带返回值的回调函数#ifdef __cplusplus}#endif#endif

hello.c

#include <stdio.h>#include <stdlib.h>#include "hello.h"void say_hello(){printf("hello\r\n");}void say_hello2(int iNum){printf("hello2 num:%d\r\n",iNum);}void say_hello3(const char *str){printf("hello3 str:%s\r\n",str);}int say_hello4(int iNum1,int iNum2){int res = iNum1 + iNum2;printf("hello4 res:%d\r\n",res);return res;}struct POINT get_mouse_position(){struct POINT temp;temp.x = 12;temp.y = 13;return temp;}struct POINT *get_position(){struct POINT *temp =NULL;temp = (struct POINT *)malloc(sizeof(struct POINT));temp->x = 10;temp->y = 20;return temp;}void release_point(struct POINT * ptrData){if(NULL != ptrData){free(ptrData);ptrData = NULL; }}void send_message(int a, callback funcPtr){printf("send_message a:%d\r\n",a);if(funcPtr != NULL)funcPtr();}int send_message2(int a, callback2 funcPtr){printf("send_message2 a:%d\r\n",a);if(funcPtr != NULL){int res= funcPtr(6);printf("回调函数的执行结果为:%d\r\n",res);}return 5;}

构建步骤,如果生成libhello.so文件那么就构建成功了

mkdir buildcd buildcmake ..make

python动态链接库基础调用

将so文件拷贝到py文件的同级目录

运行命令:

python3 main.py

目录结构如下:

├── libhello.so└── main.py

main.py

import ctypesfrom ctypes import *solib = ctypes.CDLL('./libhello.so')func_say_hello = solib.say_hellofunc_say_hello()print("func_say_hello 执行完毕!")print("============================")func_say_hello2 = solib.say_hello2func_say_hello2(2)print("func_say_hello2 执行完毕!")print("============================")func_say_hello3 = solib.say_hello3str = "I love you"func_say_hello3(str.encode("UTF-8"))print("func_say_hello3 执行完毕!")print("============================")func_say_hello4 = solib.say_hello4res = func_say_hello4(5,6)print("func_say_hello3 执行完毕!结果为:",res)print("============================")

执行结果如下:

hellofunc_say_hello 执行完毕!============================hello2 2func_say_hello2 执行完毕!============================hello3 I love youfunc_say_hello3 执行完毕!============================hello4 11func_say_hello3 执行完毕!结果为: 11============================

python动态链接库结构体调用

main.py

import ctypesfrom ctypes import *class PyPointStruct(Structure):_fields_ = [("x", c_int),("y", c_int),]solib = ctypes.CDLL('./libhello.so')func_get_mouse_position = solib.get_mouse_positionfunc_get_mouse_position.restype = PyPointStruct # 设置函数返回结果的类型为结构体resp = func_get_mouse_position()print("res2:",resp.x)print("res2:",resp.y)print("============================")func_get_position = solib.get_positionfunc_get_position.restype = POINTER(PyPointStruct) # 设置函数返回结果的类型为结构体指针resb = func_get_position()print("res3:",resb.contents.x)print("res3:",resb.contents.y)print("============================")

执行结果如下:

res2: 12res2: 13============================res3: 10res3: 20============================

python动态链接库回调函数

main.py

import ctypesfrom ctypes import *solib = ctypes.CDLL('./libhello.so') # 加载动态链接库def cb_sayhello():# 无参数的回调函数print("python hello")def cb_sayhello2(res):# 带参数有返回值的回调函数。print("python hello2,res:",res)return 1024solib = ctypes.CDLL('./libhello.so') func_send_message = solib.send_message# CFUNCTYPE定义方法的签名,第一参数表示方法的返回类型,后面开始编译参数的类型funcStruct = CFUNCTYPE(None)solib.send_message(10,funcStruct(cb_sayhello))print("============================")send_message2 = solib.send_message2# CFUNCTYPE定义方法的签名,第一参数表示方法的返回值,后面开始编译参数的类型funcStruct2 = CFUNCTYPE(c_int,c_int)send_message2(10,funcStruct2(cb_sayhello2))print("============================")

执行结果:

send_message a:10python hello============================send_message2 a:10python hello2,res: 6回调函数的执行结果为:1024============================

Note:在一个项目中,我使用python调用动态库,发现奔溃的现象。

具体问题如下,

我将python中的回调函数传递给so调用,但是so的程序中使用了多线程调用回调函数,由于python的回调函数时通过构造对象的方式调的send_message2(10,funcStruct2(cb_sayhello2)) 其中,funcStruct2(cb_sayhello2)是一个对象,因此在这个函数执行完成后会释放这个对象,在so的程序中多线程函数执行回调函数对象就已经被释放了 ,因此照成回调函数调用崩溃的情况。

代码下载地址

/download/arv002/33253778

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。