Вопрос

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.

Это было полезно?

Решение

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.

Другие советы

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top