obtuvo una respuesta en la lista de correo pitón, y después de un poco de reelaboración y más investigación me dieron exactamente lo que quería :)
vi ese puesto antes mithrandi pero no me gusta la idea de tener para declarar las funciones así. ¡Con algunas envolturas elegantes y un poco de magia de pitón esto puede funcionar y verse bien al mismo tiempo!
Para empezar, envuelva su objeto Python con código como este
cuando se encuentra en su clase de definir el método como tal
.def("createTimer", &createTimerWrapper, (bp::arg("interval"), bp::arg("function"), bp::arg("recurring") = false))
Con ese poco de envoltura se puede trabajar magia como esto
import MyLib
import time
def callMePls():
print("Hello world")
return True
class = MyLib.Class()
class.createTimer(3, callMePls)
time.sleep(1)
Para imitar el C++ por completo, también necesitamos un boost :: bind implementar ación que se puede encontrar aquí: http://code.activestate.com/recipes/440557/
Con esto, ahora podemos hacer algo como esto
import MyLib
import time
def callMePls(str):
print("Hello", str)
return True
class = MyLib.Class()
class.createTimer(3, bind(callMePls, "world"))
time.sleep(1)
EDIT:
me gusta hacer un seguimiento de mis preguntas cuando pueda. Estuve usando este código exitosamente por un tiempo, pero descubrí que esto se desmorona cuando quieres tomar la función boost :: en constructores de objetos. Hay una manera de hacerlo funcionar de manera similar a esto, pero el nuevo objeto que construye termina con una firma diferente y no funcionará con otros objetos como sí mismo.
Esto finalmente me molestó lo suficiente como para hacer algo al respecto y dado que sé más acerca de boost :: python ahora se me ocurrió una solución bastante buena para todos los convertidores. Este código aquí convertirá un pitón que se puede llamar a un objeto boost :: python < bool()>, se puede modificar fácilmente para convertirlo a otras funciones de impulso.
// 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;
}
};
Luego, en el código de inicio, es decir, BOOST_PYTHON_MODULE(), simplemente grabar el tipo mediante la creación de la estructura
BOOST_PYTHON_MODULE(Foo)
{
// Register function converter
BoostFunc_from_Python_Callable();