[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