[C++-sig] boost::python embedding return value
Stefan Seefeld
seefeld at sympatico.ca
Thu Mar 4 19:49:10 CET 2010
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
--
...ich hab' noch einen Koffer in Berlin...
More information about the Cplusplus-sig
mailing list