Python:从回调访问对象属性

Python: access to object attribute from callback

我正在尝试用回调函数设计类,该函数被传输到某个C库。需要在不更改回调参数的情况下授予对此类对象的访问权限。如何做到这一点?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from ctypes import *
...
lib = CDLL('mylibname.so')
    ...
    class A(object):
        def __init__(self):
            CALLBACK = CFUNCTYPE(c_uint32, c_void_p)
            self.callback_func = CALLBACK(A.message_callback)
            self.param = None
        def message_callback(data):
            ... #here need access to self.param
            return 0
        def set_param(self, param):
            self.param = param
    ...
    a = A()
    lib.lib_func(param1, param2, a.callback_func)

编辑:我已经用包装函数更改了类中的回调方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from ctypes import *
...
lib = CDLL('mylibname.so')

class struct_t(Structure):
    pass
struct_t._fields_ = [('next', POINTER(value_pair_t)),
                         ('key', c_char_p),
                         ('value', c_char_p)]
...
class A(object):
    def __init__(self):
        self.param = None

    def wrapper(self):
        CALLBACK = CFUNCTYPE(c_uint32, POINTER(struct_t))
        def message_callback(data):
            ... # now I have access to self here
            return 0
        return CALLBACK(message_callback)

    def set_param(self, param):
        self.param = param
...
a = A()
lib.lib_func(param1, param2, a.wrapper())

它适用于python2,但我仍然对python3有问题:

回溯(最近一次呼叫的最后一次):"调用回调函数"中的文件"ctypes/callbacks.c",第260行类型错误:"lp结构"对象不可调用

以下是同一问题的链接:奇怪的bug?


只需定义message_callback(self, data)并使用self.callback_func = A.CALLBACK(self.message_callback)。注:我用了A.CALLBACK。将其设置为类属性。为每个实例定义它是浪费时间。

例如:

丙:

1
2
3
4
5
6
typedef int (*callback_t)(void *data);

int test(const char *data, callback_t f) {
    f((void *)data);
    return 0;
}

Python:

1
2
3
4
5
6
7
8
9
10
11
12
from ctypes import *

class A(object):
    CALLBACK = CFUNCTYPE(c_uint32, c_void_p)

    def __init__(self):        
        self.callback_func = A.CALLBACK(self.message_callback)
        self.param = None

    def message_callback(self, data):
        self.param = cast(data, c_char_p).value
        return 0

演示:

1
2
3
4
5
6
7
>>> lib = CDLL('./lib.so')
>>> a = A()
>>> lib.test.argtypes = [c_char_p, A.CALLBACK]
>>> lib.test("updated", a.callback_func)
0
>>> a.param
'updated'