[C++-sig] Convert C++ Class to exposed class and back

Stefan Seefeld seefeld at sympatico.ca
Tue Feb 12 20:44:00 CET 2008

Marcus Jannes wrote:
> Okay, let me explain in detail then:


> Well, i still couldn't get this to work at runtime yet. I am not sure if it is even possible, but i got an example from a book where there is a similar case using double data instead of a class (DerivType) and it seems like doing the trick. If this can be done with boost.python instead of C API or you got any other comments please let me know. 

Again, it can't be done any less (or more) in boost.python than it can 
be done with the C API. You still face the same question (which David 
points out in the FAQ, as you noted): you need to pass some state that 
needs to be remembered, close to the function (pointer).

If the execution of that function is synchronous, i.e. if your C++ 
library does not intend to store the function pointer and call it later, 
you may get away by setting some static data during the upcall.

However, this won't work if the execution is deferred, as you may call 
fEval from within python multiple times, each time overriding the 
closure data set in the previous call.

Here is how it *might* work:

// remember the current python function
bp::object current_callable;

// implement suitable ddf_FctPtr that executes
// the current python function
DerivType call(DerivType const &argument)
   bp::object retn = current_callable(argument);
   return bp::extract<DerivType>(retn);

// The function to be called in Python. The return value is returned 
directly, not passed back by-reference.
DerivType py_fEval(bp::object function, DerivType const &argument)
   DerivType retn;
   current_callable = function;
   // assume 'call' won't be stored beyond this call, and so we can
   // be sure 'current_callable' doesn't change its value.
   fEval(call, argument, retn);
   return retn;

Now you only need to export 'py_fEval' as 'fEval' to python and you 
should be all set. Remember: this trick only works if the function 
pointer won't be retained and called asynchronously, as then 
'current_callable' may long have assumed a different value.



       ...ich hab' noch einen Koffer in Berlin...

More information about the Cplusplus-sig mailing list