복붙노트

[PYTHON] 파이썬과 ctypes : DLL에 "pointer-to-pointer"를 올바르게 전달하는 방법은 무엇입니까?

PYTHON

파이썬과 ctypes : DLL에 "pointer-to-pointer"를 올바르게 전달하는 방법은 무엇입니까?

메모리를 할당하고 그것을 반환하는 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에서이 함수에 액세스하는 파이썬 코드가 있습니다.

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 ]

나는 그 인쇄가 "4 0 1 2 3"을 보여줄 것이라고 기대하고 있지만 "4 221 221 221 221"O_O를 보여줍니다. 내가 뭘 잘못하고 있는지 알아?

해결법

  1. ==============================

    1.실제 코드 게시. C / C ++ 코드는 C 또는 C ++로 컴파일되지 않습니다. 파이썬 코드에는 구문 오류 ()가 있으며 함수 호출 Foo를 종료합니다. 아래 코드가 작동합니다. 구문과 컴파일러 오류를 고친 후에 가장 큰 문제는 __stdcall 함수를 선언했기 때문에 windll이 파이썬 코드에서 사용될 수 있습니다. 다른 옵션은 __cdecl (일반적으로 기본값)을 사용하고 파이썬 코드에서 windll 대신 cdll을 사용하는 것입니다.

    실제 코드 게시. C / C ++ 코드는 C 또는 C ++로 컴파일되지 않습니다. 파이썬 코드에는 구문 오류 ()가 있으며 함수 호출 Foo를 종료합니다. 아래 코드가 작동합니다. 구문과 컴파일러 오류를 고친 후에 가장 큰 문제는 __stdcall 함수를 선언했기 때문에 windll이 파이썬 코드에서 사용될 수 있습니다. 다른 옵션은 __cdecl (일반적으로 기본값)을 사용하고 파이썬 코드에서 windll 대신 cdll을 사용하는 것입니다.

    #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;
    }
    
    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
    
  2. from https://stackoverflow.com/questions/4213095/python-and-ctypes-how-to-correctly-pass-pointer-to-pointer-into-dll by cc-by-sa and MIT license