Pergunta

A função C. myfunc opera em um pedaço maior de dados. Os resultados são retornados em pedaços para uma função de retorno de chamada:

int myfunc(const char *data, int (*callback)(char *result, void *userdata), void *userdata);

Usando ctypes, não é grande coisa para ligar myfunc do código Python e para que os resultados sejam retornados a uma função de retorno de chamada Python. Este retorno de chamada funciona bem.

myfunc = mylib.myfunc
myfunc.restype = c_int
myfuncFUNCTYPE = CFUNCTYPE(STRING, c_void_p)
myfunc.argtypes = [POINTER(c_char), callbackFUNCTYPE, c_void_p]

def mycb(result, userdata):
    print result
    return True

input="A large chunk of data."
myfunc(input, myfuncFUNCTYPE(mycb), 0)

Mas, existe alguma maneira de fornecer um objeto Python (digamos uma lista) como dados do usuário para a função de retorno de chamada? Para armazenar os pedaços de resultado, eu gostaria de fazer, por exemplo:

def mycb(result, userdata):
    userdata.append(result)

userdata=[]

Mas não tenho idéia de como lançar a lista Python para um C_Void_P, para que ela possa ser usada na chamada para o MyFunc.

Minha solução alternativa atual é implementar uma lista vinculada como uma estrutura CTYPES, que é bastante pesada.

Foi útil?

Solução

Eu acho que você poderia usar o Python C API Para fazer isso ... talvez você possa usar um ponteiro Pyobject.

editar: Como o OP apontou nos comentários, já existe um py_object digite prontamente disponível em ctypes, então a solução é criar primeiro a ctypes.py_object objeto da lista de Python e depois lançá -la para c_void_p passar como um argumento para a função C (acho que essa etapa pode ser desnecessária como um parâmetro digitado como void* deve aceitar qualquer ponteiro, e seria mais rápido passar apenas um byref). No retorno de chamada, as etapas reversas são feitas (lançando do ponteiro vazio a um ponteiro para py_object e depois obter o valor do conteúdo).

Uma solução alternativa pode ser usar um fechamento para sua função de retorno de chamada, para que já saiba em qual lista precisa anexar os itens ...

myfunc = mylib.myfunc
myfunc.restype = c_int
myfuncFUNCTYPE = CFUNCTYPE(STRING)
myfunc.argtypes = [POINTER(c_char), callbackFUNCTYPE]


def mycb(result, userdata):
    userdata.append(result)

input="A large chunk of data."
userdata = []
myfunc(input, myfuncFUNCTYPE(lambda x: mycb(x, userdata)))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top