0

I'm trying to create a Python Function from a string and executing it. I just cannot figure it out how to execute it properly. The code I wrote doesn't return the value I would expect, but a Object of Type _PY_NoneStruct.

string code = 
R"(
def test():
    return 'hi';
)";

Py_Initialize();

auto main = PyImport_AddModule((char*)"__main__");
auto dict = PyModule_GetDict(main);

auto compiled = Py_CompileString(code.c_str(), "not a file", Py_single_input);

auto func = PyFunction_New(compiled, dict);

auto result = PyObject_CallObject(func, NULL);

What needs to be changed for this code snippet zu execute successfully?

Thank you in advance.

1 Answers1

0

The main issue is that the code

def test():
    return 'hi'

doesn't actually return anything - it just adds a function named test to the current scope. What you actually want to do is to run this string and then extract test from the dictionary that defines the scope:

PyObject *dict = NULL,
         *run_result = NULL,
         *result = NULL;

dict = PyDict_New();
if (!dict) goto done;

run_result = PyRun_String(code.c_str(), Py_file_input, dict, dict);
// the result is not useful to us (probably None)
if (!run_result) goto done;

// get the function from the module
result = PyDict_GetItemString(dict,"test");
Py_XINCREF(result);

done:
    Py_XDECREF(dict);
    Py_XDECREF(run_result);
    return result; 

At the end of all this result is a callable object like you were after.

(A more sophisticated approach would probably involve compiling code objects then using PyFunction_New but it really looks pretty complicated for anything with arguments)

DavidW
  • 29,336
  • 6
  • 55
  • 86