2012-05-22 5 views
2

У меня есть код C:Функции обратного вызова с использованием ctypes

typedef result function_callback(struct mes_t* message, void* data) 
struct mes_t 
{ 
uint32_t field1 
uint32_t field2 
void* data 
}; 
function_one(&function_callback, data) 

приложение вызывает определенные пользователем (в function_one) функции обратного вызова function_callback. В функции обратного вызова передано поле1, поле2 и параметры данных (данные обычно равны 0)

Правильно ли написан код на питоне для этого примера?

class mes_t(ctypes.Structure): 
    pass 
mes_t._fields_ = [ 
    ('field1', ctypes.c_uint32), 
    ('dfield2', ctypes.c_uint32), 
    ('data', ctypes.POINTER(ctypes.c_void_p))] 
data_t=ctypes.c_void_p 
data=data_t() 
CALLBACK=CFUNCTYPE(ccg_msg, data_t) 
cb_func=CALLBACK() 
result = function_one(ctypes.byref(cb_func), ctypes.byref(data)) 
+0

Это может помочь исправить ваш пример кода; объявления C недействительны (я предполагаю, что вы просто пропускаете точки с запятой и помещаете вещи в неправильный порядок), и неясно, что такое 'ccg_msg'. –

ответ

1

Я угадал здесь правильный способ интерпретировать ваш код. Уточненный образец сниппеты здесь:

typedef int /* or whatever */ result; 

struct mes_t 
{ 
    uint32_t field1; 
    uint32_t field2; 
    void* data; 
}; 
typedef result function_callback(struct mes_t* message, void* data); 
result function_one(function_callback fcb, void* data); 

И вот несколько примеров ctypes Python для использования function_one():

class mes_t(ctypes.Structure): 
    _fields_ = (
     ('field1', ctypes.c_uint32), 
     ('field2', ctypes.c_uint32), 
     ('data', ctypes.c_void_p)) 

result_t = ctypes.c_int; # or whatever 

callback_type = ctypes.CFUNCTYPE(result_t, ctypes.POINTER(mes_t), ctypes.c_void_p) 
function_one.argtypes = (callback_type, ctypes.c_void_p) 
function_one.restype = result_t 

data_p = ctypes.c_char_p('whatever') 

def the_callback(mes_p, data_p): 
    my_mes = mes_p[0] 
    my_data_p = ctypes.cast(data_p, ctypes.c_char_p) # or whatever 
    my_data = my_data_p.value 
    print "I got a mes_t object! mes.field1=%r, mes.field2=%r, mes.data=%r, data=%r" \ 
      % (my_mes.field1, my_mes.field2, my_mes.data, my_data) 
    return my_mes.field1 

result = function_one(callback_type(the_callback), ctypes.cast(data_p, ctypes.c_void_p)) 

Вы увидите там множество различий между этим и вашим кодом; вероятно, слишком много, чтобы дать полное объяснение всему. Однако я могу объяснить несколько отдельных частей, если некоторые из них кажутся особенно запутанными. В целом, однако, важно иметь хорошее представление о том, как работают указатели ctypes (например, вы, вероятно, не хотите, чтобы указатель на указатель на void, но это то, что сделал ваш код на Python).

+0

Вот рабочий пример: https://gist.github.com/Nican/5198719 – Nican