我对CTypes比较陌生,我一直在编写一个Python包来包装一个编译为在linux上运行的C库(我也没有访问源只有编译的共享对象和头文件。)< / p>
从头文件;我已经获得了以下函数回调签名,
typedef void (*pxgrid_notification_cb)(jw_dom_node *node, void *arg);
typedef jw_dom_node *(*pxgrid_query_cb)(jw_dom_node *request, void *arg);
typedef void (*pxgrid_connection_disconnect_cb)(pxgrid_connection *connection, PXGRID_STATUS status, void *user_data);
typedef void (*pxgrid_connection_connect_cb)(pxgrid_connection *connection, void *user_data);
typedef void (*pxgrid_connection_account_cb)(pxgrid_connection *connection, PXGRID_STATUS status, void *user_data);
typedef void (*pxgrid_connection_ssl_ctx_cb)(pxgrid_connection *connection, void *ssl_ctx, void *user_data);
typedef int (*pxgrid_log_cb)(const char * format , va_list ap);
typedef size_t(*pxgrid_password_cb)(char * passwd , size_t size,void * user_data);
对于签名中的自定义类型,我使用ctypes.Structure类将类型定义为结构。
class pxgrid_connection(Structure): pass
class jw_dom_node(Structure): pass
class va_list(Structure): pass
***作为旁注,我也尝试从库本身导出jw_dom_node类型,但是给出了无法找到符号的错误。我认为这是因为他们很可能不会从编译的代码中导出它。尝试使用以下代码;
self.jw_dom_node = c_int.in_dll(lib, "jw_dom_node")
我已经使用了c_int类型,因为我已经读过这是ctypes的默认类型。回到我之前的思路,
定义自定义结构后,然后声明签名, ***&#39; core_instance&#39;实际上是我的核心模块的表示,我的回调模块中定义了以下签名,当我的核心模块被实例化时,self作为参数传入我的回调模块的实例化。所以core_instance只是我从我的Core类引用这些类型的方式。
self.pxgrid_connection_connect_cb = CFUNCTYPE(None, POINTER(core_instance.pxgrid_connection), c_void_p)
self.pxgrid_connection_disconnect_cb = CFUNCTYPE(None, POINTER(core_instance.pxgrid_connection), c_int, c_void_p)
self.pxgrid_connection_account_cb = CFUNCTYPE(None, POINTER(core_instance.pxgrid_connection), c_int, c_void_p)
self.pxgrid_notification_cb = CFUNCTYPE(None, POINTER(core_instance.jw_dom_node), c_void_p)
self.pxgrid_query_cb = CFUNCTYPE(core_instance.jw_dom_node, POINTER(core_instance.jw_dom_node), c_void_p)
self.pxgrid_connection_ssl_ctx_cb = CFUNCTYPE(None, POINTER(core_instance.pxgrid_connection), c_void_p, c_void_p)
self.pxgrid_log_cb = CFUNCTYPE(int, POINTER(ctypes.c_char_p), core_instance.va_list)
self.pxgrid_password_cb = CFUNCTYPE(ctypes.c_size_t, POINTER(ctypes.c_char), ctypes.c_size_t, c_void_p)
self.pxgrid_message_cb = CFUNCTYPE(None, POINTER(core_instance.jw_dom_node), c_void_p)
为每个回调定义一个CFUNCTYPE后,我定义了将在我的回调中使用的实际python函数。
def on_connected(self):
print("on_connected callback has been called")
def on_disconnected(self):
print("on_disconnected callback has been called")
def on_message_cb(self):
print("on_message_cb has been called")
现在我已经创建了要调用的实际函数,我创建了我的CFUNCTYPE签名的实际实例。
self.callback__on_connected = self.pxgrid_connection_connect_cb(self.on_connected)
self.callback__connection_disconnect = self.pxgrid_connection_disconnect_cb(self.on_disconnected)
self.callback__message_cb = self.pxgrid_message_cb(self.on_message_cb)
现在在我的核心模块中,我将实际的回调对象传递给需要它们的方法调用。 (我将尝试仅包含当前问题所需的相关代码段。)
connection = POINTER(self.types.pxgrid_connection)()
self.lib.pxgrid_connection_set_connect_cb(ctypes.byref(connection), self.callbacks.callback__on_connected)
self.lib.pxgrid_connection_set_disconnect_cb(ctypes.byref(connection), self.callbacks.callback__connection_disconnect)
....Setting up addition properties for the connection
# call method to create actual connection
self.lib.pxgrid_connection_connect(connection)
# Call method to create a notification handler and pass in callback
self.handlers.create_session_notification(connection, self.callbacks.callback__message_cb)
我能够成功创建连接,连接到我尝试连接的服务器,一切都很好。然而;没有一个回调被击中。在创建我的CFUNCTYPE签名和创建实际回调的过程中,我是否缺少某些内容?或者我只是不正确地创建我的回调函数签名?
我知道这有点啰嗦,但我想提供足够的信息来帮助我接受某人的指导。
提前感谢您,如果我遗漏了您需要回答的任何信息,请告诉我们!
谢谢:)