[C++-sig] Injecting python code to a class

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Sun Mar 28 19:27:09 CEST 2004


Hi from Cambridge, UK :)

This might not be what you are after, but anyway:

I inject methods from Python all the time using a "boost.python.injector"
similar to the one mentioned in the Boost.Python tutorial. For example:

http://cvs.sourceforge.net/viewcvs.py/cctbx/scitbx/scitbx/math/gaussian.py?rev=1.7&view=auto

The injector is defined here:

http://cvs.sourceforge.net/viewcvs.py/cctbx/boost_adaptbx/boost/python.py?rev=1.1&view=auto

All my extension module imports go through a Python layer to work around
exception handling problems with certain versions of gcc, and because I add all
kinds of stuff from Python anyway. Therefore the injector doesn't add any extra
complications. If you don't want the Python layer I'd write the extra functions
in C++ using the boost::python::object facilities. Just loop over your array in
C++ and append str(element) to a boost::python::list.

BTW: I believe an array __repr__ that spits out the entire array is a very bad
idea. If the user bothers to make a C++ array instead of simply using a Python
list the C++ array is probably big, and the __repr__ output will be a nuisance
because of its size. Seeing the default __repr__ output is more helpful. If the
user really wants the content, print list(array_instance) will do the trick.
If the wrapped arrays are small it is IMO much more efficient (compile-time and
object code size) to use the "tuple_mappings". See FAQ, mention of scitbx in
connection with array wrappers.

Ralf

--- Raoul Gough <RaoulGough at yahoo.co.uk> wrote:
> I'd like to add the __repr__ and __str__ methods to container classes
> (in the indexing suite) and the easiest way to implement them is in
> Python, e.g.
> 
> def list_repr(container):
>     return repr([x for x in container])
> 
> It is possible to inject this into an existing Python class
> (e.g. "container") as follows:
> 
> container.__repr__ = new.instancemethod (list_repr, None, container)
> 
> I've been trying to do something like this from C++ code, but I don't
> have much experience with embedding Python code in C++, and can't see
> the easy way to do it. I've tried the following:
> 
>   class_< std::vector<int> > vector_int ("vector_int");
> 
>   vector_int.def (indexing::container_suite< std::vector<int> >());
> 
>   handle<> lambda_handle
>     (PyRun_String ("lambda v: repr([x for x in v])"
>                    , Py_single_input, object().ptr(), object().ptr()));
> 
>   objects::add_to_namespace (vector_int, "__repr__", object(lambda_handle));
> 
> i.e. passing None for the global and local dicts to PyRun_String, but
> this produces the following error during module initialization
> (wrapped for legibility):
> 
> >>> from example import vector_int
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> SystemError: C:\Code\22\Objects\frameobject.c:235:
>    bad argument to internal function
> 
> 
> Is there an easy way to get at the right global and local dicts for
> the PyRun_String call? I'm not sure that this would work even if I
> could pass the right parameters there, so is there a better way
> altogether to do this?


__________________________________
Do you Yahoo!?
Yahoo! Finance Tax Center - File online. File on time.
http://taxes.yahoo.com/filing.html




More information about the Cplusplus-sig mailing list