0

こんにちは @eryksun と Python の専門家:

cffi次のコマンドを使用して、dll ファイルを python にインポートしようとしています。

from cffi import FFI
ffi=FFI()
lib=ffi.dlopen('ATC3DG.DLL')

ctypesに関する以前の質問から、DLLはすべて cdeclであることがわかり(@eryksun のヒントのおかげで)、次の方法でその関数にアクセスできました。

from ctypes import *
lib=windll.LoadLibrary('ATC3DG.DLL')
lib._InitializeBIRDSystem

ただし、cffi で同等の操作が何であるかはわかりません。lib._InitializeBIRDSystemctypes で動作しますが、cffi では動作しません。なにか提案を?

ご検討いただきありがとうございます。

エリック

4

1 に答える 1

2

atc3dg.dll によってエクスポートされたシンボルは、cdecl では珍しい先頭のアンダースコアを使用します。ffi.cdefctypes で行ったのと同じように、で使用される定義にアンダースコアを追加する必要があります。

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に次のように追加する必要があります。

enum COMMUNICATIONS_MEDIA_TYPE mediaType;

また、参考までに、コンパイラは「' ' から ' unsigned __int64' への変換unsigned short、データ損失の可能性」などのいくつかの警告を出力しました。拡張モジュールの生成されたソースでは、これについてフォローアップしていません。

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 の詳細です。

于 2013-09-13T09:02:31.390 に答える