ottenuto una risposta sulla mailing list di pitone, e dopo un po 'di rielaborazione e più ricerca ho ottenuto esattamente quello che volevo :)
ho fatto vedere che post prima mithrandi ma non mi piace l'idea di avere dichiarare le funzioni in questo modo. Con alcuni involucri di fantasia e un po 'di magia pitone questo può funzionare e sembrare bello allo stesso tempo!
Per cominciare, avvolgere il vostro oggetto pitone con codice come questo
quando nella tua classe definire il metodo in questo modo
.def("createTimer", &createTimerWrapper, (bp::arg("interval"), bp::arg("function"), bp::arg("recurring") = false))
Con quel po 'di involucro si può lavorare magia come questo
import MyLib
import time
def callMePls():
print("Hello world")
return True
class = MyLib.Class()
class.createTimer(3, callMePls)
time.sleep(1)
Per simulare completamente il C++, abbiamo anche bisogno di un potenziamento :: attua bind zione che può essere trovato qui: http://code.activestate.com/recipes/440557/
Con questo, ora possiamo fare qualcosa di simile
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:
mi piace dare un seguito a mie domande quando posso. Stavo usando questo codice con successo per un po ', ma ho scoperto che questo cade a pezzi quando si desidera prendere boost :: function nei costruttori di oggetti. C'è un modo per farlo funzionare in modo simile a questo, ma il nuovo oggetto che costruisci finisce con una firma diversa e non funzionerà con altri oggetti come se stesso.
Questo finalmente mi ha infastidito abbastanza da fare qualcosa al riguardo e dato che so di più su boost :: python ora ho trovato una soluzione abbastanza adatta per tutti i convertitori. Questo codice convertirà un python callable in un oggetto boost :: python < bool()>, può essere facilmente modificato per convertirlo in altre funzioni di 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;
}
};
Poi nel codice di inizializzazione, vale a dire, BOOST_PYTHON_MODULE(), basta registrare il tipo con la creazione della struct
BOOST_PYTHON_MODULE(Foo)
{
// Register function converter
BoostFunc_from_Python_Callable();