web-dev-qa-db-ja.com

Python and ctypes: "pointer-to-pointer"をDLLに正しく渡す方法は?

メモリを割り当てて返すDLLがあります。DLLの関数は次のようになります:

void Foo( unsigned char** ppMem, int* pSize )
{
  * pSize = 4;
  * ppMem = malloc( * pSize );
  for( int i = 0; i < * pSize; i ++ ) (* ppMem)[ i ] = i;
}

また、DLLからこの関数にアクセスするpythonコードがあります:

from ctypes import *
Foo = windll.mydll.Foo
Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
mem = POINTER( c_ubyte )()
size = c_int( 0 )
Foo( byref( mem ), byref( size ) ]
print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]

printには「40 1 2 3」と表示されると思いますが、「4 221 221 221221」と表示されます。私が間違っていることのヒントはありますか?

23
grigoryvp

実際のコードを投稿してください。 C/C++コードは、CまたはC++としてコンパイルされません。 Pythonコードに構文エラー(]終了関数呼び出しFoo)があります。以下のコードは機能します。構文エラーとコンパイラエラーを修正した後の主な問題は、関数__stdcallを宣言することでした。したがって、windllは次のようになります。 Pythonコードで使用されます。他のオプションは、__cdecl(通常はデフォルト)を使用し、Pythonコードでcdllの代わりにwindllを使用することです。 。

mydll.c(cl/W4/LD mydll.c)

#include <stdlib.h>

__declspec(dllexport) void __stdcall Foo(unsigned char** ppMem, int* pSize)
{
    char i;
    *pSize = 4;
    *ppMem = malloc(*pSize);
    for(i = 0; i < *pSize; i++)
        (*ppMem)[i] = i;
}

demo.py

from ctypes import *
Foo = windll.mydll.Foo
Foo.argtypes = [POINTER(POINTER(c_ubyte)),POINTER(c_int)]
mem = POINTER(c_ubyte)()
size = c_int(0)
Foo(byref(mem),byref(size))
print size.value,mem[0],mem[1],mem[2],mem[3]

出力

4 0 1 2 3
27
Mark Tolonen