What do I use instead of PyString_AsString when loading a python module in 3.3

bbdude95 picture bbdude95 · Mar 18, 2014 · Viewed 15.3k times · Source

I am trying to load a function from python in one of my c++ programs using this function

char * pyFunction(void)
{
    char *my_result = 0;
    PyObject *module = 0;
    PyObject *result = 0;
    PyObject *module_dict = 0;
    PyObject *func = 0;
    PyObject *pArgs = 0;

    module = PyImport_ImportModule("testPython");
    if (module == 0)
    {
        PyErr_Print();
        printf("Couldn't find python module");
    }
    module_dict = PyModule_GetDict(module); 
    func = PyDict_GetItemString(module_dict, "helloWorld"); 

    result = PyEval_CallObject(func, NULL); 
    //my_result = PyString_AsString(result); 
    my_result = strdup(my_result);
    return my_result;
}

What should I use instead of PyString_AsString?

Answer

All Workers Are Essential picture All Workers Are Essential · Mar 18, 2014

Depending on the returned type from your helloWorld() function, it could vary so it's best to check it.

To handle a returned str (Python 2 unicode), then you will need to encode it. The encoding will depend on your use case but I'm going to use UTF-8:

if (PyUnicode_Check(result)) {
    PyObject * temp_bytes = PyUnicode_AsEncodedString(result, "UTF-8", "strict"); // Owned reference
    if (temp_bytes != NULL) {
        my_result = PyBytes_AS_STRING(temp_bytes); // Borrowed pointer
        my_result = strdup(my_result);
        Py_DECREF(temp_bytes);
    } else {
        // TODO: Handle encoding error.
    }
}

To handle a returned bytes (Python 2 str), then you can get the string directly:

if (PyBytes_Check(result)) {
    my_result = PyBytes_AS_STRING(result); // Borrowed pointer
    my_result = strdup(my_result);
}

Also, if you receive a non-string object, you can convert it using PyObject_Repr(), PyObject_ASCII(), PyObject_Str(), or PyObject_Bytes().

So in the end you probably want something like:

if (PyUnicode_Check(result)) {
    // Convert string to bytes.
    // strdup() bytes into my_result.
} else if (PyBytes_Check(result)) {
    // strdup() bytes into my_result.
} else {
    // Convert into your favorite string representation.
    // Convert string to bytes if it is not already.
    // strdup() bytes into my_result.
}