[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