2

次の署名を持つ関数で DLL ファイルを使用したい -

bool isValid = isImageValid((unsigned char *) buff, const __uint32& buffLen, 
                            int imageW, int imageH, __uint32 requiredSize);

さて、バフは、同等のpythonラッパーに取得している文字列から生じる必要があります

pyBuff = open(someimagefile, 'rb').read()

pyBuff は (ほとんどの場合) 大きいため、新しい c uchar 配列を割り当ててコピーするのではなく、元のバッファーを利用したいと考えています。基本的には、pyBuff オブジェクトの char バッファを取得し、ctypes (c_ubyte *) として参照します。

私がそれに最も近いのは次のとおりです。

buff = cast(pyBuff, POINTER(c_ubyte))

しかし、これが私が望むタイプかどうかはわかりません。とにかく、関数は私に次のエラーを与えます

WindowsError: exception: access violation writing 0x00000000

どんな助けでも喜んで..

また、2 つの短い質問:

  1. この DLL (参照として使用している) の既存の C ラッパーで、(これも) これを呼び出す関数が署名を持っていることを考えると、次の定義は正しいですか?(const char * buff, const __uint32& buffLen)

    byref(c_ulong(len(pyBuff)) 
    
  2. CDLL と WinDLL の違いは何ですか? また、どちらを使用するのが適切ですか?
4

1 に答える 1

0

isImageValidPython 文字列しかなく、その内容を変更しないことが確実な場合は、buff引数を type として宣言するだけc_char_pです。バッファの内容はコピーされません。

_type_コードc_char_pは「z」です。セッター関数_ctypes/cfield.c : z_setの 2.5.4 ソースでは、オブジェクトの場合、基になるポインターstrを使用するだけであることがわかります。ob_sval

1309    if (PyString_Check(value)) {
1310        *(char **)ptr = PyString_AS_STRING(value);
1311        Py_INCREF(value);
1312        return value;

ここで、マクロは次のように定義されます。

#define PyString_AS_STRING(op) (((PyStringObject *)(op))->ob_sval)

とはいえ、ソース ファイルを読み取ることができる場合は、それを変更可能なバッファーに読み取ることをお勧めします。内容を ctypesc_char配列に読み込む方法は次のとおりです (2.5.4 でテスト済み)。

読み取るテスト ファイルを作成します。

>>> open('tmp.txt', 'w').write('''\
... This is a test.''')

でファイル サイズを取得しc_uint32、バッファを作成して、ファイルの内容を読み込みます。

>>> import os
>>> from ctypes import *
>>> buffLen = c_uint32()
>>> buffLen.value = os.path.getsize('tmp.txt')
>>> buff = (c_char * buffLen.value)()
>>> open('tmp.txt').readinto(buf)
15
>>> buff.value
'This is a test.'

他の 2 つの質問については、関数プロトタイプを次のように設定します。

lib = CDLL(path_to_dll)
isImageValid = lib.isImageValid
isImageValid.argtypes = c_char_p, POINTER(c_uint32), c_int, c_int, c_uint32
isImageValid.restype = c_bool

buffLen上記のargtypes定義により、 ctypes は自動的に参照渡しされます。を明示的に使用することもできますbyref(buffLen)

CDLLこれは、呼び出し元がスタックをクリーンアップするcdecl (C 宣言) 呼び出し規約用です。これにより、 などの可変長関数が可能になりますprintfこれは、呼び出し先がスタックをクリーンアップするWinDLLstdcall 規則用です。stdcall は、主に Kernel32 関数などの 32 ビット Win32 API で使用されます。x86 呼び出し規約に関するウィキペディアの記事を参照してください。

于 2013-03-12T06:19:38.027 に答える