调用gcc编译的dll返回一个结构时,ctypes cdecl给出4个字节丢失 [英] ctypes cdecl gives 4 bytes missing when calling gcc compiled dll returning a struct
问题描述
我有一个c库(花栗鼠),我想用ctypes调用。然而,它返回一个结构函数失败?
我得到的错误是
文件qw.py,第19行,在< module>
$这是(相关的)c代码:cpBB.h中的
b = cpBBNew3(1,2,3,4)
ValueError:调用的过程没有足够的参数(缺少4个字节)或调用约定错误
b
$ b < pre class =lang-c prettyprint-override>typedef struct cpBB {
cpFloat l,b,r,t;
} cpBB;
cpBB cpBBNew3(cpFloat l,cpFloat b,cpFloat r,cpFloat t);
in 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),此特定示例可以工作。然而,在整个库中使用stdcall时,如果使用优化和新版本的GCC进行编译,则会在库的其他部分中创建分段错误,这就是为什么获得cdecl可以很好地工作的原因。
b = cpBB()
cpBBNew3(byref(b),1,2,3, 4)
I have a c library (chipmunk) that I want to call using ctypes. However, it fails on functions that return a struct?
The error I get is
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
This is the (relevant) c-code: in cpBB.h
typedef struct cpBB {
cpFloat l, b, r ,t;
} cpBB;
cpBB cpBBNew3(cpFloat l, cpFloat b, cpFloat r, cpFloat t);
in cpBB.c
cpBB cpBBNew3(cpFloat l, cpFloat b, cpFloat r, cpFloat t) {
cpBB bb = {l, b, r, t};
return bb;
}
compiled with
gcc -O3 -std=gnu99 -shared -c
gcc -O3 -std=gnu99 -shared -s
Then the python looks like
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)
This particular example works if I compile with -mrtd and use windll (using stdcall). However using stdcall on the whole library creates segmentation faults in other parts of the library when compiled with optimizations and a newish version of GCC which is why it would be nice to get cdecl working.
Depending on the size of struct and compiler/platform, cdecl may return structs by passing hidden pointer to caller-allocated struct before normal parameters. Try the following:
b = cpBB()
cpBBNew3(byref(b),1,2,3,4)
这篇关于调用gcc编译的dll返回一个结构时,ctypes cdecl给出4个字节丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!