python 调用dll 详解

准备

将动态库与py文件放在同一目录下

引入ctypes库

from ctypes import *

加载动态库

dll=CDLL('.\\InterfaceTest.dll')

数据类型

ctypes数据类型C数据类型
c_charchar
c_shortshort
c_intint
c_longlong
c_ulongunsigned long
c_floatfloat
c_doubledouble
c_char_pchar*
c_void_pvoid*

基本数据类型参数

// .cpp
// 普通加法
float add(float ina, float inb) {
  return ina + inb;
}
# .py
a=1.0
b=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;
}
# .py
a=3.0
b=4.0
c=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.0
c的类型为 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];
  }
}
# .py
nums=10
a=(c_float*nums)()
b=(c_float*nums)()
c=(c_float*nums)()
for i in range(nums):
    a[i]=i
    b[i]=1.1
dll.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];
    }
  }
}
# .py
rows=2
cols=3
temp1=c_float*cols
a=(temp1*rows)()
b=(temp1*rows)()
c=(temp1*rows)()
for i in range(rows):
    for j in range(cols):
        a[i][j]=i+j
        b[i][j]=0.5
dll.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.5
1.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];
    }
  }
}
# .py
rows=2
cols=3
a_matrix=[]
b_matrix=[]
c_matrix=[]
for i in range(rows):
    temp1=(c_float*cols)()
    for j in range(cols):
        temp1[j]=i+j+1
    a_matrix.append(cast(temp1,POINTER(c_float)))

    temp2=(c_float*cols)()
    for j in range(cols):
        temp2[j]=0.5
    b_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.5
2.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);
}
# .py
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')
# 输出
字符串复制,结果为: b'hello world.' 测试成功!

完整代码

// interface.h
#ifndef INTERFACE_H
#define INTERFACE_H

#ifdef __cplusplus
extern "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 <string.h>

#ifdef __cplusplus
extern "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

# python
from ctypes import *

dll=CDLL('.\\InterfaceTest.dll')

a=1.0
b=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.0
b=4.0
c=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=10
a=(c_float*nums)()
b=(c_float*nums)()
c=(c_float*nums)()
for i in range(nums):
    a[i]=i
    b[i]=1.1
dll.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=2
cols=3
temp1=c_float*cols
a=(temp1*rows)()
b=(temp1*rows)()
c=(temp1*rows)()
for i in range(rows):
    for j in range(cols):
        a[i][j]=i+j
        b[i][j]=0.5
dll.add_staticMatrix(a,b,c)
print('二维静态数组加法,结果为:')
for i in c:
    for j in i:
        print(j, end=" ")
    print('')
print('\n')



rows=2
cols=3
a_matrix=[]
b_matrix=[]
c_matrix=[]
for i in range(rows):
    temp1=(c_float*cols)()
    for j in range(cols):
        temp1[j]=i+j+1
    a_matrix.append(cast(temp1,POINTER(c_float)))

    temp2=(c_float*cols)()
    for j in range(cols):
        temp2[j]=0.5
    b_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')

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年8月26日
下一篇 2023年8月26日

相关推荐