首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用cffi调用__cdel修饰函数?

如何用cffi调用__cdel修饰函数?
EN

Stack Overflow用户
提问于 2013-09-13 02:19:14
回答 1查看 482关注 0票数 0

Hi @eryksun和Python专家:

我试图使用以下命令将dll文件导入到cffi中:

代码语言:javascript
复制
from cffi import FFI
ffi=FFI()
lib=ffi.dlopen('ATC3DG.DLL')

从前面关于C型的一个问题中,我知道DLL都是cdecl (感谢@eryksun的提示),我能够以以下方式访问它的函数:

代码语言:javascript
复制
from ctypes import *
lib=windll.LoadLibrary('ATC3DG.DLL')
lib._InitializeBIRDSystem

然而,我不知道在cffi中将采取什么类似的行动。lib._InitializeBIRDSystem在ctype下工作,而不是cffi。有什么建议吗?

谢谢你调查这个,

埃里克

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-13 09:02:31

atc3dg.dll导出的符号使用前导下划线,这在cdecl中是不常见的。您必须在ffi.cdef中使用的定义中添加下划线,就像对ctype一样。

代码语言:javascript
复制
import cffi

ffi = cffi.FFI()
ffi.cdef('''
enum MESSAGE_TYPE
{
    SIMPLE_MESSAGE,     // short string describing error code
    VERBOSE_MESSAGE,    // long string describing error code
};

int _InitializeBIRDSystem(void);

int _GetErrorText(
    int                 errorCode,
    char                *pBuffer,
    int                 bufferSize,
    enum MESSAGE_TYPE   type
    );
''')

lib = ffi.dlopen('atc3dg.dll')
buf = ffi.new('char[100]')

err = lib._InitializeBIRDSystem()
lib._GetErrorText(err, buf, len(buf), lib.SIMPLE_MESSAGE)
print(ffi.string(buf).decode('ascii'))

# output:
# System         : No BIRDs were found anywhere

如果配置了C编译器,则可以使用ffi.verify()。我在cffi方面不是很有经验(还没有,但看起来很有希望),所以,请稍加考虑。

我不得不对头球做一个小小的改动。在COMMUNICATIONS_MEDIA_PARAMETERS的定义中,第500行需要按以下方式添加enum

代码语言:javascript
复制
enum COMMUNICATIONS_MEDIA_TYPE mediaType;

此外,就像FYI一样,编译器打印了一些警告,比如“从'unsigned __int64‘到'unsigned short’的转换,可能会丢失数据”。在为扩展模块生成的源代码中,我还没有对此进行跟踪。

代码语言:javascript
复制
import os
import cffi
import subprocess

pth = os.path.abspath(os.path.dirname(__file__))
os.environ['PATH'] += ';%s' % pth

# preprocess: modify this for your compiler
# Using Microsoft's cl.exe that comes with VC++.
# cdef chokes on __declspec, so define DEF_FILE.
cmd = 'cl.exe /DDEF_FILE /EP %s' % os.path.join(pth, 'atc3dg.h')
hdr = subprocess.check_output(cmd, universal_newlines=True)

ffi = cffi.FFI()
ffi.cdef(hdr)

# using __declspec(dllimport) links more efficiently,
# but skipping it still works fine
lib = ffi.verify(hdr, library_dirs=[pth], libraries=['atc3dg'])
buf = ffi.new('char[100]')

err = lib.InitializeBIRDSystem()
lib.GetErrorText(err, buf, len(buf), lib.SIMPLE_MESSAGE)
print(ffi.string(buf).decode('ascii'))
# output:
# System         : No BIRDs were found anywhere

从好的方面来说,这种方法避免了前面的下划线。这是链接器在编译扩展模块时处理的ABI细节。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18777251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档