调用gcc编译的dll返回一个结构时,ctypes cdecl给出4个字节丢失 [英] ctypes cdecl gives 4 bytes missing when calling gcc compiled dll returning a struct

查看:230
本文介绍了调用gcc编译的dll返回一个结构时,ctypes cdecl给出4个字节丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个c库(花栗鼠),我想用ctypes调用。然而,它返回一个结构函数失败?



我得到的错误是

 文件qw.py,第19行,在< module> 
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可以很好地工作的原因。

解决方案根据struct和compiler / platform的大小,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆