我正在尝试使用ctypes在Python中包装C库。函数调用需要一个我使用文档实现的回调函数。问题是回调函数需要来自库的自定义对象。这是C中我试图在python中复制的代码
void outputCallback(const A* a, void* b) {
//
}
a = function1(0, 0, outputCallback, 0, 0)
头文件中A的结构定义是:
typedef struct A
{
const unsigned char* a1;
unsigned int a2;
} A;
和我对Python等效的尝试。
class A(Structure):
_fields_ = [
("a1", ?, ?),
("a2", c_int, 16)]
class Callback():
def outputCallback(self, a):
print a.a2
return 1
cb = Callback()
CMPFUNC = CFUNCTYPE(c_int, POINTER(A))
cb.cmp_func = CMPFUNC(cb.outputCallback)
cdll.LoadLibrary("library.so")
libc = CDLL("library.so")
a = libc.function1(0, 0, cb.cmp_func, 0, 0)
我在一个类中包装回调的原因是this post。基本上是我试图保持这个回调不被垃圾收集。
感谢您提供的任何帮助。
答案 0 :(得分:4)
有一些错误,有些是基本的Python错误:
from ctypes import *
class A(Structure):
_fields_ = [
("a1", c_char_p),
("a2", c_int)]
class Callback(object):
def outputCallback(self, a, b): # outputCallback(): ?
print a.contents.a1, a.contents.a2
# The prototype of the `outputCallback`
# tells that it returns nothing, `void`
cb = Callback()
CMPFUNC = CFUNCTYPE(None, POINTER(A), c_void_p) # so `restype` shoud be
# None, void
cb.cmp_func = CMPFUNC(cb.outputCallback)
libc = CDLL('library.so')
libc.function1(0, 0, cb.cmp_func, 0, 0)
测试DLL:
#include <stdio.h>
#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct A
{
const unsigned char* a1;
unsigned int a2;
} A;
int DLLEXPORT function1(int a,
int b,
void (*outputCallback)(const A* a, void* b),
int c,
int d)
{
A obj;
obj.a1 = "Hello";
obj.a2 = 5;
outputCallback(&obj, NULL);
return 0;
}
#ifdef __cplusplus
};
#endif
测试:
>gcc library.c -o library.so -shared
>python py.py
Hello 5
>