【发布时间】:2012-06-09 01:45:51
【问题描述】:
我有一个想要使用 ctypes 调用的 c 库 (chipmunk)。但是,它在返回结构的函数上失败?
我得到的错误是
File "qw.py", line 19, in <module>
b = cpBBNew3(1,2,3,4)
ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong calling convention
这是(相关的)c 代码: 在 cpBB.h
typedef struct cpBB {
cpFloat l, b, r ,t;
} cpBB;
cpBB cpBBNew3(cpFloat l, cpFloat b, cpFloat r, cpFloat t);
在 cpBB.c 中
cpBB cpBBNew3(cpFloat l, cpFloat b, cpFloat r, cpFloat t) {
cpBB bb = {l, b, r, t};
return bb;
}
编译
gcc -O3 -std=gnu99 -shared -c
gcc -O3 -std=gnu99 -shared -s
那么python看起来像
from ctypes import *
chipmunk_lib = cdll.LoadLibrary('''C:/code/pymunk/trunk/pymunk/chipmunk.dll''')
class cpBB(Structure):
pass
cpBB._pack_ = 4
cpBB._fields_ = [
('l', c_double),
('b', c_double),
('r', c_double),
('t', c_double),
]
cpBBNew3 = chipmunk_lib.cpBBNew3
cpBBNew3.restype = cpBB
cpBBNew3.argtypes = [c_double, c_double, c_double, c_double]
b = cpBBNew3(1,2,3,4)
如果我使用 -mrtd 编译并使用 windll(使用 stdcall),则此特定示例有效。然而,当使用优化和新版本的 GCC 编译时,在整个库上使用 stdcall 会在库的其他部分产生分段错误,这就是让 cdecl 正常工作的原因。
【问题讨论】:
-
请注意,如果使用 stdcall 和优化导致分段错误,那么您的代码中可能存在使用 cdecl 进行屏蔽的错误。
-
@HarryJohnston 我在这里问了这个错误:stackoverflow.com/questions/10902348/… 从duskwuff 的回答看来我不应该使用stdcall,意思是cdecl 必须是要走的路?
-
您必须使用该函数预期的调用约定来调用外部函数,因此如果您需要相同的函数指针能够指向外部(C 库)函数或内部(您的code) 函数,那么,是的,你必须坚持使用 cdecl。
-
(如果找不到更好的解决方案,一种解决方法是更改 cpBBNew3,使其将指向结构的指针作为参数之一并返回 void。)