Мне экспортировали метод в Python с помощью Python повышения, который берет повышение:: функционируйте как аргумент.
Из того, что я считал повышение:: Python должен поддерживать повышение:: функция без большого количества суеты, но когда я пытаюсь вызвать функцию с методом 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 с этим кодом
self.__class.createTimer( 3, test.timerFunc, False )
и в 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. Благодаря повышению связывают, это будет работать с в значительной степени любой функцией или методом.
Таким образом, что является синтаксисом, я должен использовать для повышения:: Python для принятия моего Python функционирует как повышение:: функция?
os.nice(increment)
Add increment to the process’s “niceness”. Return the new niceness. Availability: Unix.
из http://docs.cython.org/library/os.html#os.nice .
Есть ли причина, по которой вы не можете назвать это в детском процессе?
-121--2714632--- 2714632-получил ответ на списке рассылки Python, а через немного переработки и большее исследование я получил именно то, что хочу :)
Я видел этот пост до Митанди, но я не Как идея необходимости объявить такие функции. С некоторыми модными обертками и немного волшебством 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 );
}
, когда в вашем классе определяется метод, подобный таким образом
.def( "createTimer", &createTimerWrapper, ( bp::arg( "interval" ), bp::arg( "function" ), bp::arg( "recurring" ) = false ) )
, с этим небольшим количеством обертки, вы можете работать, как это
import MyLib
import time
def callMePls():
print( "Hello world" )
return True
class = MyLib.Class()
class.createTimer( 3, callMePls )
time.sleep( 1 )
, чтобы имитировать это
import MyLib
import time
def callMePls():
print( "Hello world" )
return True
class = MyLib.Class()
class.createTimer( 3, callMePls )
time.sleep( 1 )
, чтобы имитировать C ++ , нам также нужен усиление :: Реализация привязки, которые можно найти здесь: 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 :: Функция в конструкторах объекта. Есть способ заставить его работать аналогично этому, но новый объект, который вы построите, заканчиваются с другой подписью и не будут работать с другими объектами, такими как сами.
Это наконец-то отложило меня достаточно, чтобы сделать что-то об этом, и так как я узнаю больше о Boost :: Python, теперь я придумал довольно хорошо «подходит всем», используя преобразователи.
Этот код здесь преобразует Python Callable в Boost :: объект Python
// 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;
}
};
Тогда в вашем инициальном коде, т. Е. Boost_Python_Module (), просто зарегистрируйте тип, создавая структуру
BOOST_PYTHON_MODULE(Foo)
{
// Register function converter
BoostFunc_from_Python_Callable();