准备
将动态库与py文件放在同一目录下
引入ctypes库
from ctypes import *
加载动态库
dll=CDLL('.\\InterfaceTest.dll')
数据类型
ctypes数据类型 | C数据类型 |
---|---|
c_char | char |
c_short | short |
c_int | int |
c_long | long |
c_ulong | unsigned long |
c_float | float |
c_double | double |
c_char_p | char* |
c_void_p | void* |
基本数据类型参数
// .cpp// 普通加法float add(float ina, float inb) {return ina + inb;}
# .pya=1.0b=2.0# 定义函数的此参数类型dll.add.argtypes=[c_float,c_float]# 定义函数的返回值类型,不能省略dll.add.restype=c_float # 调用dll中的函数c=dll.add(a,b)print('普通加法,结果为:',c,'\n')
# 输出普通加法,结果为: 3.0
argtypes:定义函数的参数类型
restype:定义函数的返回值类型
指针类型参数
// .cpp// 普通加法-指针输出结果void add_ptrout(float ina, float inb, float* outc) {*outc = ina + inb;}
# .pya=3.0b=4.0c=c_float(0.0)# 不能省略#POINTER(c_float) 表示参数类型为float型指针dll.add_ptrout.argtypes=[c_float,c_float,POINTER(c_float)]dll.add_ptrout(a,b,c)# c是指针,c.value为输出的值print('普通加法指针输出,结果为:',c.value)print('c的类型为',c,'\n')
# 输出普通加法指针输出,结果为: 7.0c的类型为 c_float(7.0)
POINTER(c_float): 表示参数类型为float型指针
一维动态数组参数
// .cpp// 一维动态数组加法void add_vec(float* ina, float* inb, float* outc, int nums) {for (int idx = 0; idx < nums; ++idx) {outc[idx] = ina[idx] + inb[idx];}}
# .pynums=10a=(c_float*nums)()b=(c_float*nums)()c=(c_float*nums)()for i in range(nums):a[i]=ib[i]=1.1dll.add_vec.argtypes=[POINTER(c_float),POINTER(c_float),POINTER(c_float)]dll.add_vec(a,b,c,nums)print('一维动态数组加法,结果为:')for i in c:print(i, end=" ")print('\n')
一维动态数组加法,结果为:1.100000023841858 2.0999999046325684 3.0999999046325684 4.099999904632568 5.099999904632568 6.099999904632568 7.099999904632568 8.100000381469727 9.100000381469727 10.100000381469727
二维静态数组参数
// .cpp// 二维静态数组加法void add_staticMatrix(float ina[2][3], float inb[2][3], float outc[2][3]) {for (int r = 0; r < 2; ++r) {for (int c = 0; c < 3; ++c) {outc[r][c] = ina[r][c] + inb[r][c];}}}
# .pyrows=2cols=3temp1=c_float*colsa=(temp1*rows)()b=(temp1*rows)()c=(temp1*rows)()for i in range(rows):for j in range(cols):a[i][j]=i+jb[i][j]=0.5dll.add_staticMatrix(a,b,c)print('二维静态数组加法,结果为:')for i in c:for j in i:print(j, end=" ")print('')print('\n')
二维静态数组加法,结果为:0.5 1.5 2.51.5 2.5 3.5
二维动态数组参数
// .cpp// 二维动态数组加法void add_dynamicMatrix(float** ina, float** inb, float** outc, int rows, int cols) {for (int r = 0; r < rows; ++r) {for (int c = 0; c < cols; ++c) {outc[r][c] = ina[r][c] + inb[r][c];}}}
# .pyrows=2cols=3a_matrix=[]b_matrix=[]c_matrix=[]for i in range(rows):temp1=(c_float*cols)()for j in range(cols):temp1[j]=i+j+1a_matrix.append(cast(temp1,POINTER(c_float)))temp2=(c_float*cols)()for j in range(cols):temp2[j]=0.5b_matrix.append(cast(temp2,POINTER(c_float)))temp3=(c_float*cols)()c_matrix.append(cast(temp3,POINTER(c_float)))a_ptr=(POINTER(c_float)*rows)(*a_matrix)b_ptr=(POINTER(c_float)*rows)(*b_matrix)c_ptr=(POINTER(c_float)*rows)(*c_matrix)dll.add_dynamicMatrix(a_ptr,b_ptr,c_ptr,rows,cols)print('二维动态数组加法,结果为:')for i in range(rows):for j in range(cols):print(c_ptr[i][j], end=" ")print('')print('\n')
# 输出二维动态数组加法,结果为:1.5 2.5 3.52.5 3.5 4.5
cast(temp1,POINTER(c_float)): cast(obj, typ) 将一个ctypes实例转换为指向另一个ctypes数据类型的指针,参数obj是将转换成指针的实例(对象),typ是要转换成的指针类型。返回一个与obj引用相同块内存的指针。
append:在数组后面添加数据
字符串
// .cpp// 字符串复制void stringCopy(char* in, char* out) {strcpy(out, in);}
# .pyin_str=create_string_buffer(b'hello world.')len=sizeof(in_str)out_str=create_string_buffer(len)dll.stringCopy(in_str,out_str)print('字符串复制,结果为:',out_str.value,'测试成功!\n')
# 输出字符串复制,结果为: b'hello world.' 测试成功!
完整代码
// interface.h#ifndef INTERFACE_H#define INTERFACE_H#ifdef __cplusplusextern "C" {#endif// 普通加法_declspec(dllexport) float add(float ina, float inb);// 普通加法-指针输出结果_declspec(dllexport) void add_ptrout(float ina, float inb, float* outc);// 一维动态数组加法_declspec(dllexport) void add_vec(float* ina, float* inb, float* outc, int nums);// 二维静态数组加法_declspec(dllexport) void add_staticMatrix(float ina[2][3], float inb[2][3], float outc[2][3]);// 二维动态数组加法_declspec(dllexport) void add_dynamicMatrix(float** ina, float** inb, float** outc, int rows, int cols);// 字符串修改_declspec(dllexport) void stringModify(char* str, int len);// 字符串复制_declspec(dllexport) void stringCopy(char* in, char* out);#ifdef __cplusplus}#endif#endif
// .cpp#include "interface.h"#include #ifdef __cplusplusextern "C" {#endif // __cplusplus// 普通加法float add(float ina, float inb) {return ina + inb;}// 普通加法-指针输出结果void add_ptrout(float ina, float inb, float* outc) {*outc = ina + inb;}// 一维动态数组加法void add_vec(float* ina, float* inb, float* outc, int nums) {for (int idx = 0; idx < nums; ++idx) {outc[idx] = ina[idx] + inb[idx];}}// 二维静态数组加法void add_staticMatrix(float ina[2][3], float inb[2][3], float outc[2][3]) {for (int r = 0; r < 2; ++r) {for (int c = 0; c < 3; ++c) {outc[r][c] = ina[r][c] + inb[r][c];}}}// 二维动态数组加法void add_dynamicMatrix(float** ina, float** inb, float** outc, int rows, int cols) {for (int r = 0; r < rows; ++r) {for (int c = 0; c < cols; ++c) {outc[r][c] = ina[r][c] + inb[r][c];}}}// 字符串修改void stringModify(char* str, int len) {for (int idx = 0; idx < len; ++idx) {str[idx] += 1;}}// 字符串复制void stringCopy(char* in, char* out) {strcpy(out, in);}#ifdef __cplusplus}#endif
# pythonfrom ctypes import *dll=CDLL('.\\InterfaceTest.dll')a=1.0b=2.0# 定义函数的此参数类型dll.add.argtypes=[c_float,c_float]# 定义函数的返回值类型,不能省略dll.add.restype=c_float # 调用dll中的函数c=dll.add(a,b)print('普通加法,结果为:',c,'\n')a=3.0b=4.0c=c_float(0.0)# 不能省略#POINTER(c_float) 表示参数类型为float型指针dll.add_ptrout.argtypes=[c_float,c_float,POINTER(c_float)]dll.add_ptrout(a,b,c)# c是指针,c.value为输出的值print('普通加法指针输出,结果为:',c.value)print('c的类型为',c,'\n')nums=10a=(c_float*nums)()b=(c_float*nums)()c=(c_float*nums)()for i in range(nums):a[i]=ib[i]=1.1dll.add_vec.argtypes=[POINTER(c_float),POINTER(c_float),POINTER(c_float)]dll.add_vec(a,b,c,nums)print('一维动态数组加法,结果为:')for i in c:print(i, end=" ")print('\n')rows=2cols=3temp1=c_float*colsa=(temp1*rows)()b=(temp1*rows)()c=(temp1*rows)()for i in range(rows):for j in range(cols):a[i][j]=i+jb[i][j]=0.5dll.add_staticMatrix(a,b,c)print('二维静态数组加法,结果为:')for i in c:for j in i:print(j, end=" ")print('')print('\n')rows=2cols=3a_matrix=[]b_matrix=[]c_matrix=[]for i in range(rows):temp1=(c_float*cols)()for j in range(cols):temp1[j]=i+j+1a_matrix.append(cast(temp1,POINTER(c_float)))temp2=(c_float*cols)()for j in range(cols):temp2[j]=0.5b_matrix.append(cast(temp2,POINTER(c_float)))temp3=(c_float*cols)()c_matrix.append(cast(temp3,POINTER(c_float)))a_ptr=(POINTER(c_float)*rows)(*a_matrix)b_ptr=(POINTER(c_float)*rows)(*b_matrix)c_ptr=(POINTER(c_float)*rows)(*c_matrix)dll.add_dynamicMatrix(a_ptr,b_ptr,c_ptr,rows,cols)print('二维动态数组加法,结果为:')for i in range(rows):for j in range(cols):print(c_ptr[i][j], end=" ")print('')print('\n')in_str=create_string_buffer(b'hello world.')len=sizeof(in_str)dll.stringModify(in_str,len)print('字符串修改,结果为:',in_str.value,'测试成功!\n')in_str=create_string_buffer(b'hello world.')len=sizeof(in_str)out_str=create_string_buffer(len)dll.stringCopy(in_str,out_str)print('字符串复制,结果为:',out_str.value,'测试成功!\n')