Как конвертировать результат обратного вызова? - PullRequest
0 голосов
/ 17 декабря 2018

Я новичок в ctypes, но хочу создать функцию обратного вызова со следующей сигнатурой обратного вызова:

def autosetup_callback(p0, p1, p2):
    """This is my callback function signature
void(__stdcall *pGUIFunction)(SIndex sIndex, unsigned int statusFlag, unsigned int, const char message[512])    
    """     
    print('autosetup arguments', p0, p1, p2)


sn= c.c_uint(0)
autosetup_cb_format = c.CFUNCTYPE(sn, c.c_uint, c.c_uint, c.c_char)

Когда вызывается этот обратный вызов, я получаю следующие ошибки:

    File "_ctypes/callbacks.c", line 257, in 'converting callback result'

TypeError: an integer is required (got type NoneType)

settings: values p1,p2,p3: 0 0 0
autosetup arguments 0 0 b'\x18' ### This is what the callback should print
Exception ignored in: <function autosetup_callback at 0x000001E3D4135A60>

Есть идеи?

1 Ответ

0 голосов
/ 17 декабря 2018

В вашем примере есть некоторое несоответствие:

  • Прототип вашей функции принимает четыре аргумента, но у вас есть только три в вашей реализации Python.
  • __stdcall следует использовать WINFUNCTYPE not CFUNCTYPE.
  • sn - это экземпляр, а не тип.Первый параметр определения обратного вызова - это возвращаемое значение (void, None в Python).
  • Последний тип параметра - char[512] (затухает до char*, поэтому c_char_p требуется вопределение обратного вызова.

Вот рабочий пример. Дано:

test.c

#define API __declspec(dllexport)  // Windows-specific export

typedef int SIndex;
typedef void(__stdcall *CALLBACK)(SIndex sIndex, unsigned int statusFlag, unsigned int, const char message[512]);

CALLBACK g_callback;

API void set_callback(CALLBACK pFunc)
{
    g_callback = pFunc;
}

API void call()
{
    g_callback(1,2,3,"Hello");
}

test.py

from ctypes import *

CALLBACK = WINFUNCTYPE(None,c_int,c_uint,c_uint,c_char_p)

@CALLBACK
def autosetup_callback(p0, p1, p2, p3):
    print('autosetup arguments', p0, p1, p2, p3)

dll = CDLL('test')
dll.set_callback.argtypes = CALLBACK,
dll.set_callback.restype = None
dll.call.argtypes = None
dll.call.restype = None

dll.set_callback(autosetup_callback)
dll.call()

Выход:

autosetup arguments 1 2 3 b'Hello'
...