[C++-sig] howto convert a python list to a C++ matrix

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Thu Oct 10 01:09:17 CEST 2002


--- Stefan Seefeld <stefan.seefeld at orthosoft.ca> wrote:
> But how am I to extract the elements of the list(s) in
> boost.python style ? And how should I raise a TypeError
> if I don't find what I'm looking for ?

This is how I raise Python exceptions:

  void raise_index_error()
  {
    PyErr_SetString(PyExc_IndexError, "Index out of range.");
    boost::python::throw_error_already_set();
  }

BUT, you can do a lot better: you can tell Boost.Python how to convert
lists of lists automatically to your matrix type. Then you can simply
.def functions taking a matrix argument instead of providing wrappers
that do the conversion and then dispatch to the C++ library function.
For example:

  void foo(matrix const& m);

  def("foo", foo);

Versus with the factory approach:

  void foo(matrix const& m);

  void foo_wrapper(python::list &l)
  {
    matrix m = matrix_factory(l);
    foo(m);
  }

  def("foo", foo_wrapper);

You will have to write a wrapper for each function that uses matrix.

Attached is a stripped down version of

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cctbx/scitbx/include/scitbx/boost_python/container_conversions.h?rev=1.5&content-type=text/vnd.viewcvs-markup

If you move and customize the code from your factory function to
the code shown below you will have a general solution that avoids
the thin-wrapper clutter.

> But 'length()' doesn't appear to exist,

David preferred to deny my repeated requests to resurrect list::size()
and tuple::size() (was there in V1). Maybe if someone helps me begging
we can change his mind for the better. Here is how it works right now:

#include <boost/python/detail/api_placeholder.hpp>

          l = boost::python::len(your_list);

Ralf


  struct matrix_to_list_of_lists // to_tuple in the original file
  {
    static PyObject* convert(matrix const& a)
    {
      using namespace boost::python;
      list result;
      // your code here to generate the list of lists
      return incref(result.ptr()); 
    }
  };

  // This is a "custom lvalue converter". See also: Boost.Python FAQ
  struct matrix_from_list_of_lists // from_python in the original file
  {
    matrix_from_list_of_lists()
    {
      boost::python::converter::registry::push_back(
        &convertible,
        &construct,
        boost::python::type_id<matrix>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
      using namespace boost::python;
      // your "factory" code here
      // return 0; // if the input object is not convertible
      return obj_ptr; // if the input object is convertible
    }

    static void construct(
      PyObject* obj_ptr,
      boost::python::converter::rvalue_from_python_stage1_data* data)
    {
      using namespace boost::python;
      void* storage = (
        (rvalue_from_python_storage<matrix>*)
          data)->storage.bytes;
      new (storage) matrix();
      data->convertible = storage;
      matrix& result = *((matrix*)storage);
      // now set the elements of the matrix using *obj_ptr
      // again similar to your "factory" code
      // for error detection use
      // if (PyErr_Occurred()) throw_error_already_set();
    }
  };

Usage:

     boost::python::to_python_converter<matrix, matrix_to_list_of_lists>();
     matrix_from_list_of_lists();


__________________________________________________
Do you Yahoo!?
Faith Hill - Exclusive Performances, Videos & More
http://faith.yahoo.com




More information about the Cplusplus-sig mailing list