Does anyone know how to use either PyCode_New or new.code()?? Specifically I want to use new.code() and new.function() to generate some python functions from strings, which I can then call in python at some later time. My trouble is I can find exactly zero documentation on the use of these functions :( Any help would be greatly appreciated. Cheers, Anders
anders langlands wrote:
Does anyone know how to use either PyCode_New or new.code()?? Specifically I want to use new.code() and new.function() to generate some python functions from strings, which I can then call in python at some later time.
Not knowing what PyCode_New or new.code() do (do you have a pointer ?), can't you use boost::python::exec() to convert strings to executable code ? (David, http://www.boost.org/libs/python/doc/ doesn't seem to contain the 'new' documentation for exec and exec_file yet. Is that intentional ?) Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...
Hi Stefan, Well PyCode_New is undocumented as far as I can see, and the header doesn't even name the arguments! new.code is documented in the library reference under module new. Its documentation is equally illuminating: it simply says "An interface to PyCode_New"... boost::python::exec sounds like exactly what I want... but I can find no documentation for this either, do you have I link? Nor can I find it in any of the boost::python headers. we're using boost 1_33_1 here at the moment. A On 9/11/06, Stefan Seefeld <seefeld@sympatico.ca> wrote:
anders langlands wrote:
Does anyone know how to use either PyCode_New or new.code()?? Specifically I want to use new.code() and new.function() to generate some python functions from strings, which I can then call in python at some later time.
Not knowing what PyCode_New or new.code() do (do you have a pointer ?), can't you use boost::python::exec() to convert strings to executable code ?
(David, http://www.boost.org/libs/python/doc/ doesn't seem to contain the 'new' documentation for exec and exec_file yet. Is that intentional ?)
Regards, Stefan
--
...ich hab' noch einen Koffer in Berlin... _______________________________________________ C++-sig mailing list C++-sig@python.org http://mail.python.org/mailman/listinfo/c++-sig
anders langlands wrote:
boost::python::exec sounds like exactly what I want... but I can find no documentation for this either, do you have I link? Nor can I find it in any of the boost::python headers. we're using boost 1_33_1 here at the moment.
Ah, well, I added it after the 1_33_1 release. It will be included in the 1_34 release (in case that is of any help). However, the implementation is really simple, so you may as well include the code directory: namespace boost { namespace python { object exec(str string, object global, object local) { // should be 'char const *' but older python versions don't use 'const' yet. char *s = python::extract<char *>(string); PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); } } } This executes 'string' in the context of 'global' and 'local'. The latter two are (potentially empty) dictionaries. Once execution has successfully terminated, 'global' will contain whatever objects 'string' injected into them such as type definitions and other objects. You can then extract these from 'global' and call them from C++. See for example http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/exe... HTH, Stefan -- ...ich hab' noch einen Koffer in Berlin...
Thanks stefan, that does indeed look pretty simple! However, is there any way I can do this with having my own interpreter? The problem I am trying to solve is this: I have a large class library I want to bind to python. Everything in the library (Derived) is derived ultimately from a single class, Base. Now I have functions to serialize and deserialize objects to disk. The deserialize function returns a Derived object as a Base*. When this Base* is passed back to python, python doesn't know that it's actually a Derived object, and it would be nice if it did. I basically want to be able to automatically cast the Base object to whichever flavour of Derived object it actually is in python. No all my objects support the functions typeId() and typename() to get information about what they are. So the solution I've come up with is this. I just store a big dict or list in the globals which maps typeId's to functions. These functions do the conversion of the base type to the derived type and the whole thing looks something like this: ------- def castDerivedTypeA( obj ): return DerivedTypeA( obj ) def castDerivedTypeB( obj ): return DerivedTypeB( obj ) _globalCastsDict = { DerivedTypeATypeId : castDerivedTypeA, DerivedTypeBTypeId : castDerivedTypeB, } def cast( obj ): return _globalCastsDict[ obj.typeId() ]( obj ) -------- Now obviously with a large class library it's going to be tedious and error-prone to maintain all those functions etc by hand. So what I'd like is to automatically generate the code in C++ at binding time. What I'd like is to do something like: BOOST_PYTHON_MODULE( _mymodule ) { class_<DerivedA,bases<Base> >( "DerivedA" ) ; exec( "code for castDerivedA function", current_interpreter.globals(), current_interpreter.locals() ); } Is it possible to get the globals from the currently running interpreter without actually writing the interpreter executable yourself? I realise I could just write my own interpreter and all would be fine and dandy, but I'd like this to be able to work even if I'm running in the standard python interrpreter A On 9/11/06, Stefan Seefeld <seefeld@sympatico.ca> wrote:
anders langlands wrote:
boost::python::exec sounds like exactly what I want... but I can find no documentation for this either, do you have I link? Nor can I find it in any of the boost::python headers. we're using boost 1_33_1 here at the moment.
Ah, well, I added it after the 1_33_1 release. It will be included in the 1_34 release (in case that is of any help).
However, the implementation is really simple, so you may as well include the code directory:
namespace boost { namespace python { object exec(str string, object global, object local) { // should be 'char const *' but older python versions don't use 'const' yet. char *s = python::extract<char *>(string); PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); } } }
This executes 'string' in the context of 'global' and 'local'. The latter two are (potentially empty) dictionaries. Once execution has successfully terminated, 'global' will contain whatever objects 'string' injected into them such as type definitions and other objects. You can then extract these from 'global' and call them from C++. See for example
http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/exe...
HTH, Stefan
--
...ich hab' noch einen Koffer in Berlin... _______________________________________________ C++-sig mailing list C++-sig@python.org http://mail.python.org/mailman/listinfo/c++-sig
anders langlands wrote:
Thanks stefan, that does indeed look pretty simple!
However, is there any way I can do this with having my own interpreter?
The problem I am trying to solve is this:
I have a large class library I want to bind to python. Everything in the library (Derived) is derived ultimately from a single class, Base. Now I have functions to serialize and deserialize objects to disk. The deserialize function returns a Derived object as a Base*. When this Base* is passed back to python, python doesn't know that it's actually a Derived object, and it would be nice if it did. I basically want to be able to automatically cast the Base object to whichever flavour of Derived object it actually is in python.
No all my objects support the functions typeId() and typename() to get information about what they are. So the solution I've come up with is this. I just store a big dict or list in the globals which maps typeId's to functions. These functions do the conversion of the base type to the derived type and the whole thing looks something like this:
I'm not sure I understand the purpose of your downcasting. Those derived python classes don't offer any additional attributes over what 'Base' already has, or do they ? If not, what advantage do you get from having the type names differ, instead of using your own type system (provided by 'typeId()' and 'typename()' ? If you really want to generate python types for the many C++ classes, and you can do the conversion at runtime (as opposed to compile-time), you may consider doing all of this from within a python module, by means of the 'type()' constructor. But again, I don't yet understand what you are aiming at, since that won't give you anything you couldn't get by directly querying an object's typeId(). Thanks, Stefan -- ...ich hab' noch einen Koffer in Berlin...
Sorry, I assumed it was clear since I know exactly what I mean! All the derived types do indeed define many additional methods that I want to use. By type() constructor, do you mean doing: b = getDerivedObjectAsBasePointer # This would fail as doSomeDerivedFunction is only defined for Derived, but python thinks b is a Base* # b.doSomeDerivedFunction() d = Derived( b ) d.doSomeDerivedFunction() This is basically what I want to do, but I want that to be hidden from the user. I want to do the type-checking and construction automatically. So I'd wrap getDerivedObjectAsBasePointer with a pure python function, getDerivedObject, defined in my module's __init__.py. I'd like to generate the code for this python function automatically from C++ at module initialization time, since I know the typenames of all my classes then, and each of them has to register itself anyway, so *if* I can get access to the globals, I can define the dict which defines the functions for doing run-time type() constructors on my base class pointers. Does this make it any clearer? This doesn't gain me anything over doing the type() constructors manually in python, but I'd like to save users this extra leg work. It'll make the resulting scripts easier to read as well. A On 9/12/06, Stefan Seefeld <seefeld@sympatico.ca> wrote:
Thanks stefan, that does indeed look pretty simple!
However, is there any way I can do this with having my own interpreter?
The problem I am trying to solve is this:
I have a large class library I want to bind to python. Everything in the library (Derived) is derived ultimately from a single class, Base. Now I have functions to serialize and deserialize objects to disk. The deserialize function returns a Derived object as a Base*. When this Base* is passed back to python, python doesn't know that it's actually a Derived object, and it would be nice if it did. I basically want to be able to automatically cast the Base object to whichever flavour of Derived object it actually is in python.
No all my objects support the functions typeId() and typename() to get information about what they are. So the solution I've come up with is
anders langlands wrote: this.
I just store a big dict or list in the globals which maps typeId's to functions. These functions do the conversion of the base type to the derived type and the whole thing looks something like this:
I'm not sure I understand the purpose of your downcasting. Those derived python classes don't offer any additional attributes over what 'Base' already has, or do they ? If not, what advantage do you get from having the type names differ, instead of using your own type system (provided by 'typeId()' and 'typename()' ?
If you really want to generate python types for the many C++ classes, and you can do the conversion at runtime (as opposed to compile-time), you may consider doing all of this from within a python module, by means of the 'type()' constructor.
But again, I don't yet understand what you are aiming at, since that won't give you anything you couldn't get by directly querying an object's typeId().
Thanks, Stefan
--
...ich hab' noch einen Koffer in Berlin... _______________________________________________ C++-sig mailing list C++-sig@python.org http://mail.python.org/mailman/listinfo/c++-sig
anders langlands wrote:
Sorry, I assumed it was clear since I know exactly what I mean!
All the derived types do indeed define many additional methods that I want to use.
While in python you can construct types at runtime (you don't even need the python parser for that !), in C++ you can't. All your C++ API reflection has to happen at compile-time. You may then rewrap the results however you want from inside a running python instance.
By type() constructor, do you mean doing:
I mean something like ---- from base import Base Derived = type('Derived', (Base,), {}) ---- which lets you create a new type 'Derived' in a functional way. Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...
participants (2)
-
anders langlands -
Stefan Seefeld