函数boost的Python方法

2024-10-01 11:30:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个使用boostpython导出到Python的方法,它以boost::函数作为参数。在

从我读到的boost::python应该支持boost::function,而不需要太多的麻烦,但是当我试图用python方法调用函数时,它会给我这个错误

Boost.Python.ArgumentError: Python argument types in
    Class.createTimer(Class, int, method, bool)
did not match C++ signature:
    createTimer(class Class {lvalue}, unsigned long interval, 
    class boost::function<bool _cdecl(void)> function, bool recurring=False)

我用这个代码从python调用它

^{pr2}$ <>和在C++中定义为

boost::int32_t createTimer( boost::uint32_t interval, boost::function< bool() > function, bool recurring = false );

这里的目标是一个计时器类,在这里我可以做一些类似的事情

class->createTimer( 3, boost::bind( &funcWithArgs, arg1, arg2 ) )

创建执行funcWithArgs的计时器。多亏了boost bind,这将与几乎任何函数或方法一起工作。在

那么,要将python函数作为boost::function接受,需要使用什么语法呢?在


Tags: 方法函数参数bindfunctionclass计时器bool
1条回答
网友
1楼 · 发布于 2024-10-01 11:30:34

在python邮件列表上找到了答案,经过一番修改和更多的研究,我得到了我想要的东西:)

在mithrandi之前,我确实看过那篇文章,但我不喜欢必须那样声明函数的想法。有了一些花哨的包装和一些python魔术,这可以工作,同时看起来很好!在

首先,用如下代码包装python对象

struct timer_func_wrapper_t
{
    timer_func_wrapper_t( bp::object callable ) : _callable( callable ) {}

    bool operator()()
    {
        // These GIL calls make it thread safe, may or may not be needed depending on your use case
        PyGILState_STATE gstate = PyGILState_Ensure();
        bool ret = _callable();
        PyGILState_Release( gstate );
        return ret;
    }

    bp::object _callable;
};

boost::int32_t createTimerWrapper( Class* class, boost::uint64_t interval, bp::object function, bool recurring = false )
{
    return class->createTimer( interval, boost::function<bool ()>( timer_func_wrapper_t( function ) ), recurring );
}

在类中定义方法时,如下所示

^{pr2}$

有了那小小的包装,你就能像这样变魔术了

import MyLib
import time

def callMePls():
    print( "Hello world" )
    return True

class = MyLib.Class()

class.createTimer( 3, callMePls )

time.sleep( 1 )

完全模仿C++,我们还需要一个Booo::绑定实现,这里可以找到:http://code.activestate.com/recipes/440557/

有了这些,我们现在可以做这样的事情了

import MyLib
import time

def callMePls( str ):
    print( "Hello", str )
    return True

class = MyLib.Class()

class.createTimer( 3, bind( callMePls, "world" ) )

time.sleep( 1 )

编辑:

我喜欢尽我所能地回答我的问题。我曾经成功地使用过这段代码,但是我发现当你想在对象构造函数中使用boost::function时,这段代码就崩溃了。 有一种方法可以使它的工作方式与此类似,但是您构造的新对象最终会有一个不同的签名,并且不会与其他类似的对象一起工作。在

这终于让我有了足够的麻烦来做些什么,因为我对boost::python有了更多的了解,所以我想出了一个非常好的使用转换器的“万能”解决方案。 这里的代码将把python可调用转换为boost::python<;bool()>;对象,可以很容易地修改为转换为其他boost函数。在

// Wrapper for timer function parameter
struct timer_func_wrapper_t
{
    timer_func_wrapper_t( bp::object callable ) : _callable(callable) {}

    bool operator()()
    {
        return _callable();
    }

    bp::object _callable;
};

struct BoostFunc_from_Python_Callable
{
    BoostFunc_from_Python_Callable()
    {
        bp::converter::registry::push_back( &convertible, &construct, bp::type_id< boost::function< bool() > >() );
    }

    static void* convertible( PyObject* obj_ptr )
    {
        if( !PyCallable_Check( obj_ptr ) ) return 0;
        return obj_ptr;
    }

    static void construct( PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data )
    {
        bp::object callable( bp::handle<>( bp::borrowed( obj_ptr ) ) );
        void* storage = ( ( bp::converter::rvalue_from_python_storage< boost::function< bool() > >* ) data )->storage.bytes;
        new (storage)boost::function< bool() >( timer_func_wrapper_t( callable ) );
        data->convertible = storage;
    }
};

只需在PYTHON模块中创建BOOST,然后输入BOOST

BOOST_PYTHON_MODULE(Foo)
{
    // Register function converter
    BoostFunc_from_Python_Callable();

相关问题 更多 >