[C++-sig] boost::python embedding return value

Neal Becker ndbecker2 at gmail.com
Thu Mar 4 19:59:45 CET 2010


Stefan Seefeld wrote:

> Neal,
> 
> I should have read your mail more carefully before replying. Sorry for
> that.
> 
> 
> On 03/04/2010 01:35 PM, Neal Becker wrote:
>> Stefan Seefeld wrote:
>>
>>    
>>> On 03/04/2010 11:59 AM, Neal Becker wrote:
>>>      
>>>> int main () {
>>>>     Py_Initialize();
>>>>
>>>>     object main_module = import("__main__");
>>>>     object main_namespace = main_module.attr("__dict__");
>>>>
>>>>     try {
>>>>       object result = exec ("import sys\n"
>>>> "sys.path.append('./')\n"
>>>> "import test_embed\n"
>>>> "test_embed.five_square()\n",
>>>> main_namespace);
>>>>       int five_squared = extract<int>   (result);
>>>>       std::cout<<   five_squared<<   '\n';
>>>>     }
>>>>     catch (error_already_set const&) {
>>>>       PyErr_Print();
>>>>     }
>>>> }
>>>>
>>>>
>>>> test_embed.py:
>>>> --------------------
>>>> def five_square ():
>>>>       return 5 ** 2
>>>>
>>>> I get:
>>>> ./test_embed
>>>> TypeError: No registered converter was able to produce a C++ rvalue of
>>>> type int from this Python object of type NoneType
>>>>        
> 
> The problem is that you shouldn't attempt to extract anything from the
> return value of an exec() call. It will contain None if everything goes
> well. If not, the C API returns a null-pointer, which boost.python
> translates into an err_already_set exception.
> 
> I'm not exactly sure what you attempt to do. If you really want to
> evaluate an expression (inclusively a function call), you should use
> eval(), instead of exec().
> 
> The typical usage of exec() will be to run some code, then inspect the
> global namespace to inspect any "side-effects" of this execution.
> Notably, you may have your Python module store objects in the namespace,
> and then let your C++ code extract and use them.
> For example
> 
>    std::string code =
>    "import test_embed\n"
>    "result = test_embed.five_square()";
> 
>    object = exec(code, global, global);
>    int result = extract<int>(global["result"]);
> 
> Hope this helps,
>          Stefan
> 

OK.  I had assumed, since it returned an object, that I could call a 
function and get back the python result.  I didn't use eval, because eval is 
restricted to 1 expression, and so couldn't do something like:
'''
sys.path.append('./')
import module
module.F (3)'''

which is what I was trying to do




More information about the Cplusplus-sig mailing list