我的C dll来源:
#include<stdio.h>
typedef struct {
int nums[5];
int tp;
} Sample;
float read_float(Sample s, float* arg){
return arg[1];
}
调用它的Python代码的来源:
from ctypes import *
class PySample(Structure):
_fields_ = [("nums", c_int * 5),
("tp", c_int)]
if __name__ == "__main__":
libp = CDLL(r"PathToMyDLL")
rf = libp.read_float
rf.restype = c_float
s = PySample()
for i in range(5):
s.nums[i] = (11,22,33,44,55)[i]
s.tp = 101
print(rf(s, (c_float*3)(0.4, 0.5, 0.6)))
使用gcc -shared编译并运行Python代码后,我得到一些随机的小数字。 但是,如果我将C函数的签名更改为:
float read_float(float* arg, Sample s)
和相应的Python打印调用:
print(rf((c_float*3)(0.4, 0.5, 0.6), s))
(即在定义和函数调用中改变参数的顺序)然后我得到正确的0.5
这不是理想的行为。我在这里做错了什么以及为什么会这样?
(64位Windows和C代码的Python 3.4.1使用gcc 4.8.1(MinGw-W64)编译)
答案 0 :(得分:2)
如果添加argtypes
声明,则在32位编译并与32位Python一起使用时,您的示例正常工作:
rf.argtypes = [PySample, POINTER(c_float)]
但是在64位Python中,如果失败了。我发现更改argtypes
以使用指向结构的指针使其工作,即使C按值传递结构。
rf.argtypes = [POINTER(PySample), POINTER(c_float)]
但是,如果我改变你的功能来修改结构,它也会在Python中修改它。从C调用函数并实际传递值并未按预期修改调用者中的结构,因此这似乎是64位ctypes
中的错误。