如何使用python将数组传递给用c编写的共享库(.dll)

时间:2012-03-26 14:08:41

标签: python c arrays dll ctypes

test.dll文件的功能代码:

double __cdecl add(int len,double array[]){}

(我已经在vc中测试过了)

python代码:

import ctypes
from ctypes import *

N=...
arr=(c_double*N)()
...
...
dll=CDLL("test.dll")
sum=dll.add(c_int(N),byref(arr))

print sum

但是python代码不起作用, 并且“sum”总是等于N.(例如,当N = 10时,它打印“sum = 10”) 怎么了?

2 个答案:

答案 0 :(得分:9)

在ctypes中传递数组镜像在C中传递一个数组,即你不需要传递对它的引用,因为数组已经是对它的第一个元素的引用。

from ctypes import *

N = ...
arr=(c_double*N)()
dll=CDLL("test.dll")
sum=dll.add(c_int(N),arr)

print sum

在讨论与qsort的接口时,可以在callbacks section下的ctypes文档中看到这方面的一个例子。

编辑:根据David Heffernan的评论,您还需要dll.add.restype = c_double,否则ctypes将假定返回的类型为c_int

答案 1 :(得分:0)

这里的问题是该函数被定义为

double __cdecl add(int len, double array[]) { }

但是,除非您为其指定返回值的类型,否则ctypes默认为int。这类似于将C中的函数声明为

int __cdecl add(int len, double array[]);

由于声明和定义不匹配,因此您的代码具有未定义的行为,即:

  

- 定义的函数的类型与表示被调用函数的表达式(6.5.2.2)指向的类型(表达式)不兼容。

在这种特定情况下,您运行的是一个在寄存器中返回整数和浮点值的体系结构;但intdouble返回值存储在不同的寄存器中。现在,在此ABI中包含类型int的返回值的寄存器恰好包含N作为剩余。正确的返回值包含在浮点寄存器中,但由于ctypes期望得到int,所以它从未使用过。

因此,正确的解决方法是

dll.add.restype = c_double