Подтвердить что ты не робот

Python и ctypes: как правильно передать "указатель на указатель" в 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;
}

Кроме того, у меня есть код python, который обращается к этой функции из моей 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 ]

Я ожидаю, что print покажет "4 0 1 2 3", но показывает "4 221 221 221 221" O_O. Любые намеки на то, что я делаю неправильно?

4b9b3361

Ответ 1

Опубликовать фактический код. Код C/С++ не компилируется как C или С++. Код Python имеет синтаксические ошибки (] завершение функции вызова Foo). Ниже приведен код. Основная проблема после исправления синтаксиса и ошибок компилятора заключалась в объявлении функции __stdcall, поэтому windll может использоваться в коде Python. Другой вариант - использовать __cdecl (обычно по умолчанию) и использовать cdll вместо windll в коде Python.

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