[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:
The injector is defined here:
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.
--- 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.
More information about the Cplusplus-sig