3

I try to compile the example code from Python website https://docs.python.org/3/extending/embedding.html. Everything works fine except the following line:

 pName = PyUnicode_DecodeFSDefault(argv[1]);

I have Python 3.6 installed on my MacOS El Captain. My make file looks like the following:

call_function:     call_function.o        
    gcc -o call_function call_function.o -export-dynamic -L/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin -lpython3.6m -lpthread -lm -ldl -lutil


call_function.o:call_function.cpp    
    gcc -c call_function.cpp -I/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m

When I compile the C++ code, I get the following error:

gcc -c call_function.cpp -I/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m
call_function.cpp:16:13: error: use of undeclared identifier    'PyUnicode_DecodeFSDefault'
pName = PyUnicode_DecodeFSDefault(argv[1]);
        ^
1 error generated.

Does anyone know how to fix the above error? I would greatly appreciated for your help.

Here is the complete example code:

#include <Python/Python.h>
#include <Python/unicodeobject.h>

int main(int argc, char *argv[])
{
PyObject *pName, *pModule, *pDict, *pFunc;
PyObject *pArgs, *pValue;
int i;

if (argc < 3) {
    fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
    return 1;
}

Py_Initialize();
pName = PyUnicode_DecodeFSDefault(argv[1]);
// pName = PyUnicode_FromString(argv[1]);  <-- also gives me an error

/* Error checking of pName left out */

pModule = PyImport_Import(pName);
Py_DECREF(pName);

if (pModule != NULL) {
    pFunc = PyObject_GetAttrString(pModule, argv[2]);
    /* pFunc is a new reference */

    if (pFunc && PyCallable_Check(pFunc)) {
        pArgs = PyTuple_New(argc - 3);
        for (i = 0; i < argc - 3; ++i) {
            pValue = PyLong_FromLong(atoi(argv[i + 3]));
            if (!pValue) {
                Py_DECREF(pArgs);
                Py_DECREF(pModule);
                fprintf(stderr, "Cannot convert argument\n");
                return 1;
            }
            /* pValue reference stolen here: */
            PyTuple_SetItem(pArgs, i, pValue);
        }
        pValue = PyObject_CallObject(pFunc, pArgs);
        Py_DECREF(pArgs);
        if (pValue != NULL) {
            printf("Result of call: %ld\n", PyLong_AsLong(pValue));
            Py_DECREF(pValue);
        }
        else {
            Py_DECREF(pFunc);
            Py_DECREF(pModule);
            PyErr_Print();
            fprintf(stderr,"Call failed\n");
            return 1;
        }
    }
    else {
        if (PyErr_Occurred())
            PyErr_Print();
        fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
    }
    Py_XDECREF(pFunc);
    Py_DECREF(pModule);
}
else {
    PyErr_Print();
    fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
    return 1;
}
Py_Finalize();
return 0;
}

3 Answers3

1

I figure out what the problem is. The include <Python/Python.h> statement is actually linked to /System/Library/Frameworks/Python.framework/Versions/Current which currently is Python2.7. I have installed Python 3.6 on my Mac and even I include /Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m in my make file, it's still referred to the Python.h file in MacOS's Python 2.7 folder. I tried to change the symbolic link of the Current to the new 3.6 folder and it's not letting me make the changes. Does anybody know how to change the symbolic link of the Python2.7 current folder so my gcc would look into the Python 3.6 folder for Python.h instead?

arulmr
  • 8,620
  • 9
  • 54
  • 69
  • You should edit this into the question, don't post it as an answer. – ShadowRanger Mar 21 '17 at 00:48
  • 1
    @ShadowRanger The first part of this post really is more of an answer -- the OP has determined the cause of the problem. We actively discourage people from editing their question to include their own answer, and encourage them to post an answer instead. The second part (*Does anybody know how to change the symbolic link...*) should probably be a separate question. – Caleb Mar 21 '17 at 01:53
  • @user7601973 do you have any solution? – badcode Feb 05 '21 at 10:10
1

It is been a long time since this question got posted, but the solution that I came up is as follows,

char * full_cls_name = argv[1];
Py_Initialize();
pName = PyString_FromString(full_cls_name);

You should also check whether argv[1] exists or not?

  • According to https://stackoverflow.com/questions/48849047/replacing-pystring-fromstring-method-in-python-3 this method was renamed to PyUnicode_FromString – botero May 08 '20 at 13:12
0

This is what worked for me.

gcc -o call  $(python3-config --cflags --embed) multiply_embed.c $(python3-config --ldflags --embed)

I got the answer from this post - answer by Ciro Santilli Путлер.

I also got module not found error when running the code, which was overcome by setting the PYTHONPATH variable in the zshrc file as described here.