[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. 

[snip]
> 
> 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
type).

-Jonathan

---------------- 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>&)>
void
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));

  return;
}

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

BOOST_PYTHON_MODULE(call_from_python_with_list)
{
  class_<call_me>("call_me")
    .def( "f", &call_from_python_with_list< call_me, &call_me::f>)
    ;
}





More information about the Cplusplus-sig mailing list