2

I'm a bit confused. I'm trying to do some C++ and Python integration, but it's less than straightforward. I'm not using Boost, because I couldn't get Boost::Python to compile properly. But that's another story.

Currently, here's what I'm doing in C++:

//set everything up
PyObject* py_main_module = PyImport_AddModule("__main__");
PyObject* py_global_dict = PyModule_GetDict(py_main_module);
PyObject* py_local_dict = PyDict_New();
PyObject* py_return_value;

PyRun_SimpleString(data.c_str()); //runs Python code, which defines functions

//call a function defined by the python code
py_return_value = PyRun_String("test()", Py_single_input, py_global_dict, py_local_dict);

//attempt to check the type of the returned value
if(py_return_value != NULL) {
    //this is the problem: all of these print 0
    cout << PyList_Check(py_return_value) << endl;
    cout << PySet_Check(py_return_value) << endl;
    cout << PyFloat_Check(py_return_value) << endl;
} else {
    cout << "IT WAS NULL?!" << endl;
}

The Python program (input to the C++ program as the string named "data"):

def test():
    derp = 1.234
    #derp = [1, 2, 3, 4]
    #derp = set([1, 2, 3, 4])
    return derp

Now, the problem is that the type checks aren't working. They all return 0, regardless of whether the Python function is returning a float, a list, or a set. What am I doing wrong?

Bonus points if anyone can tell me why the call to PyRun_String prints the returned value in the console. It's really annoying.

2 Answers 2

3

From the docs:

int Py_eval_input

The start symbol from the Python grammar for isolated expressions; for use with Py_CompileString().

int Py_file_input

The start symbol from the Python grammar for sequences of statements as read from a file or other source; for use with Py_CompileString(). This is the symbol to use when compiling arbitrarily long Python source code.

int Py_single_input

The start symbol from the Python grammar for a single statement; for use with Py_CompileString(). This is the symbol used for the interactive interpreter loop.

Py_single_input evaluates the string as a statement. Statements don't inherently return anything, so you'll get None back from PyRun_String. Use Py_eval_input instead to evaluate the string as an expression and get a result.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! That does indeed solve both of my problems. What is the difference between evaluating as a statement or as an expression, besides the return value? Or is that the only difference?
Expressions can produce values; examples are x - 1, foo(blah), lambda x:y. Statements are usual lines of code in Python, and include things like assignments x = 1 and function definitions. An expression by itself can be a statement, but not all statements can be treated as expressions. (You can think of an expression as anything you could pass to a function).
2

Changing Py_single_input to Py_eval_input seems to resolve both issues.

The former treats the string as part of the interpreter loop, while the latter evaluates a single expression and gives you an object back. (I'm not sure what the return value means in the former case, but it's not the value of the expression.)

EDIT: Just tested it, and as per nneonneo's answer below, the result with Py_single_input is indeed Py_None.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.