[C++-sig] Re: getting result from the interpreter -- boost-python
David Abrahams
dave at boost-consulting.com
Tue Oct 14 14:25:53 CEST 2003
[Dirk & Joel, please see below]
Benjamin Collar <collar at gamic.com> writes:
> Greetings
>
> Yesterday I posted a question that hasn't been commented on until now...No
> problem. It was kind of a messy question anyway.
>
> I've sort of found an answer. However, the example in the documentation does
> not work properly in my environment.
^^^^^^^^^^^^^^
...which is... ??
> Here's the example:
>
> handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
> dict main_namespace(handle<>(borrowed( PyModule_GetDict(main_module.get())
> )));
> handle<>( PyRun_String("result = 5 ** 2", Py_file_input,
> main_namespace.ptr(), main_namespace.ptr()) );
> int five_squared = extract<int>( main_namespace["result"] );
>
> This will not compile:
> main.cc: In function `int main(int, char**)':
> main.cc:33: error: variable declaration is not allowed here
> main.cc:35: error: request for member `ptr' in `main_namespace()', which is
> of non-aggregate type `boost::python::dict ()()'
> main.cc:35: error: request for member `ptr' in `main_namespace()', which is
> of non-aggregate type `boost::python::dict ()()'
> main.cc:36: error: invalid types `boost::python::dict ()()[const char[7]]'
> for array subscript
Posting error messages which cite errors on line 33 for a 5-line
example is bound to be confusing for anyone, so it's a bit difficutlt
to help you. There's a lot of information missing.
> I can get it to compile if I dereference the handle<> when declaring
> main_namespace--but then it throws and exception.
The problem is that the line declaring "main_namespace" is declaring
a function which returns a dict. But where did you get that line?
It's not in any of the docs I can find.
I'd write:
// Retrieve the main module
python::object main_module = python::extract<python::object>(
PyImport_AddModule("__main__")
);
// Retrieve the main module's namespace
python::object main_namespace = main_module.attr("__dict__");
or, if your code has to run on broken compilers like vc6:
// Retrieve the main module
python::object main_module = python::extract<python::object>(
PyImport_AddModule("__main__")
)();
// Retrieve the main module's namespace
python::object main_namespace(main_module.attr("__dict__"));
In fact, I would like it very much if we could change the examples in
the tutorial to use this style. It's far simpler and clearer, IMO.
> What I have below will
> compile and gives me the right result but seems messy and perhaps leaks? If
> someone could tell me the 'right' way to do this, I'd appreciate it:
There are no leaks here AFAICT.
> handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
> handle<> main_namespace(borrowed( PyModule_GetDict(main_module.get()) ));
> handle<> rs( PyRun_File(fp, const_cast<char *>("test.py")),
> Py_file_input, main_namespace.get(), main_namespace.get()));
> fclose(fp);
> object x(main_namespace);
> dict m_n = extract<dict>(x);
> int pi = extract<int>(m_n["i"]);
Building a dict is really unneccessary here. You can just as easily
index an object:
int pi = extract<int>(x["i"]);
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list