Python 在Ctypes中传递结构

Python 在Ctypes中传递结构,python,ctypes,Python,Ctypes,我一直在尝试在Ctypes中传递一个结构。但是函数调用抛出了一个格式错误 这是我的C函数: typedef struct Point2Struct { double x, y; } Point2; Point2 test(Point2 k) { return k; } python调用如下所示: class Point2(Structure): _fields_ = [('x',c_double),('y',c_double)] lib.test.argt

我一直在尝试在Ctypes中传递一个结构。但是函数调用抛出了一个格式错误

这是我的C函数:

typedef struct Point2Struct {   
    double x, y;
    } Point2;

Point2 test(Point2 k)
{
  return k;
}
python调用如下所示:

class Point2(Structure):
    _fields_ = [('x',c_double),('y',c_double)]

lib.test.argtypes=[Point2]
lib.test.restype=Point2
p = Point2(1.1, 2.2)

g = lib.test(p)

print g.x, g.y
当我通过CDLL调用函数时,我得到:

ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong calling convention
ValueError: Procedure probably called with too many arguments (16 bytes in excess)
有了温德尔,我得到了:

ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong calling convention
ValueError: Procedure probably called with too many arguments (16 bytes in excess)
我在Windows7下使用(Mingw)gcc将C代码编译成DLL

 gcc -shared -o test.dll test.o
我还尝试将.so文件用于:

gcc -shared -Wl,-soname,test-o test.so -fPIC test.c
但我也犯了同样的错误


我做错了什么?我应该使用任何特定选项进行编译吗?

要处理大于8字节的聚合返回,MinGW和Microsoft的编译器都会隐式地向调用者中的本地内存传递指针。看起来您的gcc版本默认在被调用方中弹出此指针。然而,ctypes/libffi是用visualstudio构建的,需要微软的约定,在调用方中处理这个问题。这就是为什么它抱怨缺少4个字节

如果您使用的是gcc 4.6+,则有一种方法可以启用Microsoft的约定:

被叫人\u pop\u聚合\u返回(编号)

在32位i?86——目标上,如果调用者负责弹出隐藏指针和其余参数(数字等于零),或者如果被调用者负责弹出隐藏指针(数字等于一),则可以通过这些属性控制内存中的聚合返回。默认的i386 ABI假设被调用方弹出堆栈以隐藏指针

gcc 4.7似乎使用Microsoft约定作为Windows目标的默认设置:

请注意,在32位i386 Windows目标上,编译器假定调用者弹出堆栈作为隐藏指针

在Windows上使用GCC4.6.3进行测试时,它仍然使用“默认i386 ABI”。设置函数属性解决了问题:

Point2 test(Point2 k)
    __attribute__((callee_pop_aggregate_return(0)));

当然,您的里程数可能会有所不同。更好的是,如果您控制规范,我认为只使用通过引用传递的显式输出参数更简单。

您是否尝试过显式地将
\u declspec(dllexport)
\u cdecl
添加到函数中?或者,您是否尝试过编写C代码,以与
ctypes
相同的方式加载和使用DLL?谢谢。我想我会通过传递推荐信来做到这一点。