Got odpowiedź na listy Pythona, a po trochę przeróbek i dalszych badań dostałem dokładnie to, co chciałem :)
widziałem to stanowisko przed mithrandi ale nie podoba mi się pomysł posiadania zadeklarować takie funkcje. Z fantazyjnymi opakowaniami i odrobiną magii Pythona może to działać i wyglądać dobrze w tym samym czasie!
Aby rozpocząć, zakończyć swój obiekt Pythona z kodem jak ten
gdy w klasie zdefiniować metodę Podobnie jak
.def("createTimer", &createTimerWrapper, (bp::arg("interval"), bp::arg("function"), bp::arg("recurring") = false))
Z tą odrobiną owijki można pracować magii jak to
import MyLib
import time
def callMePls():
print("Hello world")
return True
class = MyLib.Class()
class.createTimer(3, callMePls)
time.sleep(1)
Aby całkowicie naśladować C++, potrzebujemy również narzędzia boost :: bind acji, które można znaleźć tutaj: http://code.activestate.com/recipes/440557/
Dzięki temu możemy teraz zrobić coś takiego
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:
Lubię śledzić na moje pytania, kiedy tylko mogę. Używałem tego kodu z powodzeniem przez pewien czas, ale odkryłem, że to się rozpada, gdy chcesz wziąć boost :: function w konstruktorach obiektów. Istnieje sposób, aby działał podobnie, ale nowy obiekt, który stworzysz, kończy się innym podpisem i nie będzie działał z innymi obiektami, takimi jak on.
To w końcu podsyciło mnie na tyle, że mogłem coś z tym zrobić, a ponieważ wiem więcej o boost :: python, wymyśliłem całkiem niezłe rozwiązanie "pasuje do wszystkich" za pomocą konwerterów. Ten kod skonwertuje pytona wywoływanego na boost :: python < bool()> obiekt, można go łatwo zmodyfikować, aby przekonwertować go na inne funkcje doładowania.
// 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;
}
};
Następnie w kodzie init tj BOOST_PYTHON_MODULE(), po prostu zarejestrować typ tworząc struct
BOOST_PYTHON_MODULE(Foo)
{
// Register function converter
BoostFunc_from_Python_Callable();