[capi-sig] Easy way to Return Value from 1 line of Embedded Python?

Jerry Krinock support at sheepsystems.com
Thu May 27 16:26:39 CEST 2010


In a C program I need to unpickle a Python pickle which is generated by someone's Python program.  A Python newbie, I was able to do this, but only by writing a little python script file and loading it as a module.  But reading from a script file is fragile, has lots of possible errors to handle as you can see below, and is silly since there's only one line of Python.

I'd therefore like to create the Python module from a string constant, as with PyRun_SimpleString(), instead of reading a file.  But I can't find a function like that which returns a value.  Or I just don't know how.

Certainly there must be a simpler way to do this...

Thank you,

Jerry Krinock

***** somePython.py *****************************

#!/usr/bin/env python

from pickle import loads

def unpickle(x):
    return loads(x)


***** My C "Proof of Concept" Function **********

#include <Python/Python.h>  // Running on Mac OS X

char* PythonUnpickle(char* pickle) {
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;
    char* unpickledString = NULL ;
    
    Py_Initialize();
    PyRun_SimpleString("import sys"); 
    PyRun_SimpleString("sys.path.append(\"/Users/jk/Documents/Programming/Python/\")"); 
    
    pName = PyString_FromString("somePython");
     
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    
    if (pModule != NULL) {
        
        pFunc = PyObject_GetAttrString(pModule, "unpickle");
        /* pFunc is a new reference */
        
        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(1);
            
            // Create the argument to unpickle()
            pValue = PyString_FromString(pickle);
            if (!pValue) {
                Py_DECREF(pArgs);
                Py_DECREF(pModule);
                fprintf(stderr, "Cannot convert argument\n");
                return NULL ;
            }
            // Set the argument into the pArgs tuple
            PyTuple_SetItem(pArgs, 0, pValue);
            
            // Run the python unpickle() function, get result pValue
            pValue = PyObject_CallObject(pFunc, pArgs) ;
            Py_DECREF(pArgs) ;
            // Convert the Python string pValue to a C string
            if (pValue != NULL) {
                unpickledString = PyString_AsString(pValue) ;
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return  NULL ;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find 'unpickle' function\n") ;
        }
        Py_XDECREF(pFunc);
        
        
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load python script file\n");
    }
    Py_Finalize() ;
    
    return unpickledString ;
}




More information about the capi-sig mailing list