boost :: python:使用回调

时间:2014-02-11 11:10:54

标签: python c++ boost-python

我有这样的标题(fingisdk.h)文件:

#ifndef FINGISDK_H_
#define FINGISDK_H_

#include "fingienum.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*fingi_event)(FINGI_EVENT_ID eventId, char* msg);

FINGI_EVENT_ID start_fingi_sdk(char* ini_file_location);
FINGI_EVENT_ID download_room_info(char** roominfo);

void register_fingi_sdk_status_event_listener(fingi_event pointer_to_listener_fnc);


#ifdef __cplusplus
}
#endif
#endif

然后我为这个编写了一个python Wrapper:

#include <fingisdk.h>
#include <fingienum.h>
#include <boost/python.hpp>


BOOST_PYTHON_MODULE(libpythonWrapper)
{
    using namespace boost::python;
    def("start_fingi_sdk", start_fingi_sdk);


}

用于调用它的python文件是这样的:

import libpythonWrapper

print libpythonWrapper.start_fingi_sdk('file_location.ini')

到目前为止这个工作正常。但是,我无法找到如何公开double双指针 功能:

FINGI_EVENT_ID download_room_info(char** roominfo);

回调函数:

void register_fingi_sdk_status_event_listener(fingi_event pointer_to_listener_fnc);

有人能指点我一些文件或帮我解决吗

三江源


编辑1:

在搞砸了一下之后,我想出了如何做指针指针功能。 Python不支持指针,因此必须包装download_room_info(char ** roominfo)以返回简单的字符串:

std::string download_room_info_python_wrapper() {
    char * value;
    FINGI_EVENT_ID result = download_room_info(&value);
    return std::string(value);
}

然后:

def("download_room_info", download_room_info_python_wrapper);

仍在寻找回调函数的解决方案

1 个答案:

答案 0 :(得分:3)

所以你想把这个API绑定到Python:

typedef void (*fingi_event)(FINGI_EVENT_ID eventId, char* msg);
void register_fingi_sdk_status_event_listener(fingi_event);

这是一个寄存器函数,它接受一个带有eventId和字符串的函数。好吧,让我们定义一个我们自己的(当然,在外部“C”,因为API是):

void my_callback(FINGI_EVENT_ID eventId, char* msg)
{
  // do something
}

现在我们可以为寄存器函数编写一个包装器:

void my_register()
{
  register_fingi_sdk_status_event_listener(my_callback);
}

绑定它:

def("my_register", my_register);

这一切都应该有效。但它没用,因为我们在回调中实际上没有做任何事情。所以这会导致一个子问题,你怎么能在回调中做任何事情呢?我的一个想法是你应该创建自己的函数注册机制,它允许你将Python回调函数注册到类似全局PyObject的东西,它将被设置为Python函数并使用Boost Python调用:

boost::python::object g_callback;
void my_callback(FINGI_EVENT_ID eventId, char* msg)
{
  if (g_callback)
    g_callback(eventId, msg);
}

现在只需让用户分配全局回调:

void set_callback(boost::python::object func)
{
  g_callback = func;
  register_fingi_sdk_status_event_listener(my_callback);
}

def("set_callback", set_callback);

然后在Python中:

def callback(eventId, msg):
  print eventId, msg

set_callback(callback)

我认为这应该是关于它的。如果您的回调API支持像许多回调API那样的“void * userData”参数,那么整个过程会更容易。然后我们使用它来存储PyObject或其他有用的东西。但是API缺乏这一点,所以我们在某个地方停留在某处,以便记住要调用的函数。