Search code examples
c++python-c-api

How to convert PyObjects to C data types?


I am working on a project where I have to convert a user input C++ string variable to python executable code, I'm using the Python C API, so I have to go through the intermediary of converting the C++ string to a C string (or character array). Once I get there, I can't get the value to print once the code has been run. I'm searching for what the proper function in the Python C API is. I've tried PyString_AsString(), PyBytes_AsString(), and PyObject_AsUTF8Stringso far. Each of these functions has caused a memory issue when I try and run it with the code below. I've had to hard reboot my system with these three.

    Py_Initialize();
//the expected output, the player's output, and the compare functions
//PyObject* expectAnswer; //the expected answer for the level
PyObject* main = PyImport_AddModule("_main_");
PyObject* globalDictionary = PyModule_GetDict(main);
PyObject* localDictionary = PyDict_New();
PyObject* result = PyRun_String(cPlayerString, Py_file_input, globalDictionary, localDictionary);



Py_Finalize();

I am wondering whether I'm just not using the right call. const char* PyUnicode_AsData() looks promising, but I still have no idea whether I'd need to convert what I have into Unicode first.

Thanks for all the help!


Solution

    1. You're missing all error checking. Pretty much every Python C API call has a return value that indicates if an error has occurred, usually a NULL pointer. You must check these and handle the error if it has happened. I'll charitably assume you omitting this for the sake of a concise question.

    2. __main__; double underscore.

    3. Probably your real issue: read the documentation about the start tokens. Py_file_input evaluates the string as if it were a Python file (i.e. an arbitrarily long collection of statements). A Python file doesn't "return" anything, and so result is probably a None object - you could always inspect it to confirm this. Your options are:

      • to use the token Py_eval_input which handles a single expression only and does return the result.

      • use the fact that a collection of statements (Py_file_input) will alter the local dictionary - any variables assigned to will be available in the dictionary afterwards and you can access those.

    4. The object you eventually get is (probably) not going to be a string, so calling string functions on it may crash it (Py*_Check functions are used to confirm the type and avoid this sort of crash). You probably want to use the generic PyObject functions in the first instance. PyObject_Print/Str/Repr may be what you're after.