[C++-sig] Re: will custom lvalue converters be supported?

Jonathan Brandmeyer jbrandmeyer at earthlink.net
Thu Jul 22 00:05:34 CEST 2004

On Wed, 2004-07-21 at 11:14, Igor Lapshin wrote:
> Hi Ralf and Dave, 
> Thanks for the fast response.
> That's exactly the case:  there are already hundreds of functions
> written with that "write-back" requirement long before we decided to use
> Python and it seems to me that writing thin wrappers for all of them is
> quite problematic. Moreover, the new functions are still being
> written...
> The classes, which are used as parameters for those functions, derived
> from stl::vector, but have additional member-functions, which I cannot
> remove without affecting hundreds of already written functions. Those
> additional members are used only internally and not from Python, thus
> tuple or sequence functionality is sufficient. 

> Is there any way to write a generic thin wrapper supporting "write back"
> for various functions with different signatures but with very limited
> set of types (we have some 5 types)?

Sure.  Here is something.  Hopefully, it can be generalized/specialized
as needed for your requirements, and isn't too non-portable (er, it
works with gcc 3.3.4 and 3.4.1 ...).  It takes advantage of the idea
that the function pointers passed to class_<T>::def() can be free
functions that take a T pointer or reference as their first argument.

If you have no choice but to go the route of wrapping the type to be
list-like, I would recommend the vector_indexing_suite<>.  (as a side
note, it supports basic slicing, but not extended slicing of the wrapped


---------------- A somewhat generic thin wrapper ---------------------
#include <vector>
#include <boost/python.hpp>

using namespace boost::python;

template <typename T, void (T:: *T_fn)(std::vector<double>&)>
call_from_python_with_list( T* This, boost::python::list py_arg1)
  int arg1_size = extract<int>(py_arg1.attr("__len__")());
  std::vector<double> cpp_arg1(arg1_size);

  // Initialize cpp_arg1 from py_arg1
  for (int i = 0; i < arg1_size; ++i)
    cpp_arg1[i] = extract<double>(py_arg1[i]);
  // Call the C++ mem fun that takes an lvalue.
  (This->*T_fn)( cpp_arg1);

  // overwrite py_arg1 with data from cpp_arg1
  py_arg1.attr("__delslice__")(0, arg1_size);
  for (std::vector<double>::iterator i = cpp_arg1.begin(); 
      i < cpp_arg1.end(); ++i)
    py_arg1.append( object(*i));


struct call_me
  void f( std::vector<double>& arg)
    // do something to modify the vector.

    .def( "f", &call_from_python_with_list< call_me, &call_me::f>)

More information about the Cplusplus-sig mailing list