Python使用Ctypes调用C/C++动态库

本文介绍了如何在C/C++和Python之间通过ctypes库进行高效通信,包括定义输入输出结构体、调用C函数、处理C++类型以及在Windows和Linux平台上编译动态链接库和调用过程。
摘要由CSDN通过智能技术生成

1.前言

C/C++语言的优点是执行效率高,但开发效率和内存安全性较低,比较考虑编程水平。在开发算法的过程中,使用python语言能够快速的完成算法原型的设计并验证算法,但在实际应用过程中一般难以有好的速度效率,因而需要使用C。据笔者在项目实践中,一般而言C语言比python语言在算法执行速度上快约100多倍(windows和linux平台)。

2.Ctypes

ctypes是Python的内置库,用于加载动态链接库并创建能够直接传入C函数的对象。

3.调用方法

笔者在搜集了相关资料后,总结出了以下几种常见用法。C语言实际开发过程中比较麻烦,但Ctypes只能调用C类型而不能调用C++类型。没关系,可以在传入传出参数使用C类型,而中间开发过程中可以使用C++、STL库,最后导出方式为extern "C"。

3.1Python端

为了方便起见,可以传入结构体指针,首先定义结构体:

class InputData(Structure):
    _fields_=[("a",c_int),#整型变量
              ("b",c_double),#浮点型变量
              ("c",POINTER(c_int)),#整型变量指针(一维数组)
              ("d",POINTER(c_double)),#浮点型变量指针(一维数组)
             ]



#创建对象
input_data=InputData()

#对象赋值
input_data.a=1
input_data.b=2.0

#数组赋值
cc=[1,1,1]
input_data.c=(c_int*len(cc))(*cc)
dd=[2.0,2.0,2.0]
input_data.d=(c_double*len(dd))(*dd)

同理也可以定义输出结构体:

class OutputData(Structure):
    _fields_=[("m",c_int),
              ("n",c_double),
              ("p",POINTER(c_int)),
              ("q",POINTER(c_double)),
             ]

3.2 C端

首先定义输入输出结构体,特别注意的是,参数类型和名称顺序一定要对应!

//输入结构体
struct InputData {
	int a;
	double b;
    int* c;
    double *d;
};
//输出结构体
struct InputData {
	int m;
	double n;
    int* p;
    double *q;
};

在C中定义导出的函数:

//windows平台
extern "C" _declspec(dllexport) void fuction(InputData * input_data, OutputData * output_data);

//linux平台:
extern "C" __attribute__((visibility("default"))) void fuction(InputData * input_data, OutputData * output_data);

在定义的函数中实际上可以使用任意的C++类型,但要注意的是,由于C++有很多个版本的标准,在不同标准下的某些代码编写规范不同,需要注意!可能在C++17是允许写的,在C++11上编译就通不过。

3.3编译动态库

编译命令

//windows平台
cl -O2 /LD 你的C代码文件.cpp

//linux平台
g++ 你的c代码文件.cpp -fPIC -shared -o 你的输出文件名.so

由此得到了.dll库或者.so库

3.4 调用动态库

#windows平台
dll=cdll.LoadLibrary("你的动态库名字.dll")
dll.fuction.argtypes=(POINTER(InputData),POINTER(OutputData))#结构体输入数据,结构体输出数据
get_c=dll.fuction(input_data,output_data)


#linux平台
dll=cdll.LoadLibrary("你的动态库名字.so")
dll.fuction.argtypes=(POINTER(InputData),POINTER(OutputData))#结构体输入数据,结构体输出数据
get_c=dll.fuction(input_data,output_data)

访问返回结果的方法也很简单:

print(output_data.m)
print(output_data.n)

#传出数据中,m作为p的数据长度,C语言的数组传出时跟一个长度较好。
for i in range(output_data.m):
    print(output_data.p[i])

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值