Problem with PyMethodDef and non-static functions
Hello list! I'm using Python/C to be able to have simple Python scripts in my application. I was free of problems until I switched from using static and global functions to using non-static class methods: python.cpp:101: error: argument of type ‘PyObject* (Python::)(PyObject*, PyObject*)’ does not match ‘PyObject* (*)(PyObject*, PyObject*)’ After some time I understood that this was a problem that a little tweaking around wouldn't solve. So I want to ask you guys if you can describe how to get around this. I wouldn't want to add any additional dependencies such as SWIG or Boost. Please also note that I'm not that experienced with Python. And I want to keep this as clean/simple as possible! :-) Thanks in advance! -- Jon Kristensen
Jon Kristensen wrote:
Hello list!
I'm using Python/C to be able to have simple Python scripts in my application. I was free of problems until I switched from using static and global functions to using non-static class methods:
python.cpp:101: error: argument of type ‘PyObject* (Python::)(PyObject*, PyObject*)’ does not match ‘PyObject* (*)(PyObject*, PyObject*)’
After some time I understood that this was a problem that a little tweaking around wouldn't solve. So I want to ask you guys if you can describe how to get around this. I wouldn't want to add any additional dependencies such as SWIG or Boost. Please also note that I'm not that experienced with Python.
As you have found out, ordinary pointers and pointers to members are fundamentally incompatible with each other, i.e. there is no way to cast from one to the other. You have to implement a wrapper around your method call. Something like: struct MyType { int func(int); }; PyObject *my_method(PyObject *self, PyObject *args) { CxxType *object = extract_object_from_self(self); int arg = extract_arg(args); int result = object->func(arg); return convert_result_to_python(result); } But of course, all this forward and backward extraction / conversion business makes the above highly inconvenient and non-scalable, so you may indeed want to give boost.python a try as your project grows. :-) HTH, Stefan -- ...ich hab' noch einen Koffer in Berlin...
tor 2006-09-28 klockan 14:50 -0400 skrev Stefan Seefeld:
Jon Kristensen wrote:
Hello list!
I'm using Python/C to be able to have simple Python scripts in my application. I was free of problems until I switched from using static and global functions to using non-static class methods:
python.cpp:101: error: argument of type ‘PyObject* (Python::)(PyObject*, PyObject*)’ does not match ‘PyObject* (*)(PyObject*, PyObject*)’
After some time I understood that this was a problem that a little tweaking around wouldn't solve. So I want to ask you guys if you can describe how to get around this. I wouldn't want to add any additional dependencies such as SWIG or Boost. Please also note that I'm not that experienced with Python.
As you have found out, ordinary pointers and pointers to members are fundamentally incompatible with each other, i.e. there is no way to cast from one to the other. You have to implement a wrapper around your method call. Something like:
struct MyType { int func(int); };
PyObject *my_method(PyObject *self, PyObject *args) { CxxType *object = extract_object_from_self(self); int arg = extract_arg(args); int result = object->func(arg); return convert_result_to_python(result); }
Thanks for your reply. I don't understand the following: * What purpose does the struct MyType serve? * What's extract_object_from_self? (Don't find anything on Google.)
But of course, all this forward and backward extraction / conversion business makes the above highly inconvenient and non-scalable, so you may indeed want to give boost.python a try as your project grows. :-)
OK, perhaps I will! :-)
HTH, Stefan
-- Jon Kristensen
Jon Kristensen wrote:
Thanks for your reply. I don't understand the following:
* What purpose does the struct MyType serve?
You ask for a way to bind a C++ member function to a python method. But a member is always a member of some object, so MyType provides one. Both, MyType as well as MyType::func are placeholders for your own code.
* What's extract_object_from_self? (Don't find anything on Google.)
Indeed. You have to write that yourself, i.e. a function to extract a MyType pointer (again, placeholder for your own object pointer) from the python wrapper through which the member function is to be invoked. Boost.python does all that for you automagically... Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...
participants (2)
-
Jon Kristensen -
Stefan Seefeld