Embedding Python in C: Error in linking - undefined reference to PyString_AsString

2024/10/10 8:22:18

I am trying to embed a python program inside a C program. My OS is Ubuntu 14.04

I try to embed python 2.7 and python 3.4 interpreter in the same C code base (as separate applications). The compilation and linking works when embedding python 2.7 but not for the python 3.4. It fails during the linker stage.

Here is my C code (just an example not real code)

simple.c

#include <stdio.h>
#include <Python.h>int main(int argc, char *argv[])
{PyObject *pName, *pModule, *pFunc, *pValue;char module[] = "get_version";char func[] = "get_version";char module_path[] = ".";Py_Initialize();PyObject *sys_path = PySys_GetObject("path");PyList_Append(sys_path, PyUnicode_FromString(module_path));pName = PyUnicode_FromString(module);pModule = PyImport_Import(pName);Py_DECREF(pName);if(pModule != NULL){pFunc = PyObject_GetAttrString(pModule, func);if (pFunc && PyCallable_Check(pFunc)){pValue = PyObject_CallObject(pFunc, NULL);if (pValue != NULL) {printf("Python version: %s\n", PyString_AsString(pValue));Py_DECREF(pValue);}else {Py_DECREF(pFunc);Py_DECREF(pModule);PyErr_Print();fprintf(stderr,"Call failed\n");return 1;}}}Py_Finalize();return 0;
}

get_version.py

import sysdef get_version():version = '.'.join(str(v) for v in sys.version_info[:3])print("version: ", version)return version

I compile the program using gcc. First with compiling and linking flags set to python 2.7 I run the compilation and linking by using following command:

gcc `python-config --cflags` simple.c `python-config --ldflags`

The flags expand as:

python-config --cflags: -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes

python-config --ldflags: -L/usr/lib/python2.7/config-x86_64-linux-gnu -L/usr/lib -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

It works fine without any issues. When I try to compile the same with python3.4 flags it fails:

gcc `python3-config --cflags` simple.c `python3-config --ldflags`

The flags expand as:

python-config --cflags: -I/usr/include/python3.4m -I/usr/include/python3.4m -Wno-unused-result -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes

python-config --ldflags: -L/usr/lib/python3.4/config-3.4m-x86_64-linux-gnu -L/usr/lib -lpython3.4m -lpthread -ldl -lutil -lm -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

Error message:

simple.c: In function ‘main’:
simple.c:27:17: warning: implicit declaration of function ‘PyString_AsString’ [-Wimplicit-function-declaration]printf("Python version: %s\n", PyString_AsString(pValue));^
simple.c:27:17: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
/tmp/ccaoMdTo.o: In function `main':
/home/vagrant/c_python_api/simple.c:27: undefined reference to `PyString_AsString'
collect2: error: ld returned 1 exit status

I tried by changing the order in which linker objects are specified. But no luck. Any idea why this would be the case?

Thanks for the help!!

Answer

Python 3 does not have PyString_AsString any more; the Python 3 str correspond to Python 2 unicode objects; the names of the functions for handling str in Python 3 are PyUnicode_-prefixed in the C-API.

Thus this line:

printf("Python version: %s\n", PyString_AsString(pValue));

could be changed to use PyUnicode_AsUTF8 on Python 3:

#if PY_MAJOR_VERSION >= 3
printf("Python version: %s\n", PyUnicode_AsUTF8(pValue));
#else
printf("Python version: %s\n", PyString_AsString(pValue));
#endif

(Not that passing NULL to printf %s will have undefined behaviour, so you'd want to check that a non-NULL pointer was returned)

https://en.xdnf.cn/q/69920.html

Related Q&A

How can I add properties to a class using a decorator that takes a list of names as argument?

I would like to add many dummy-properties to a class via a decorator, like this:def addAttrs(attr_names):def deco(cls):for attr_name in attr_names:def getAttr(self):return getattr(self, "_" +…

How to reshape only last dimensions in numpy?

Suppose I have A of shape (...,96) and want to reshape it into (...,32,3) keeping both lengths and number of preceding dimensions, if ever, intact.How to do this?If I writenp.reshape(A, (-1, 32, 2))it…

Relative import of submodule

In Python, how do I perform the equivalent of the followingimport http.clientbut using a relative import:from . import http.client import .http.clientFor a package http in the current package? I want …

Python regular expression to replace everything but specific words

I am trying to do the following with a regular expression:import re x = re.compile([^(going)|^(you)]) # words to replace s = I am going home now, thank you. # string to modify print re.sub(x, _, s)T…

How do I raise a window that is minimized or covered with PyGObject?

Id been using the answer provided in the PyGTK FAQ, but that doesnt seem to work with PyGObject. For your convenience, here is a test case that works with PyGTK, and then a translated version that does…

How to bind multiple widgets with one bind in Tkinter?

I am wondering how to bind multiple widgets with one "bind".For expample: I have three buttons and I want to change their color after hovering.from Tkinter import *def SetColor(event):event.w…

Iterate a large .xz file line by line in python

I have a large .xz file (few gigabytes). Its full of plain text. I want to process the text to create custom dataset. I want to read it line by line because it is too big. Anyone have an idea how to do…

Detect multiple circles in an image

I am trying to detect the count of water pipes in this picture. For this, I am trying to use OpenCV and Python-based detection. The results, I am getting is a little confusing to me because the spread …

Need guidance with FilteredSelectMultiple widget

I am sorry if it question might turn to be little broad, but since I am just learning django (and I am just hobbyist developer) I need some guidance which, I hope, will help someone like me in the futu…

Django: determine which user is deleting when using post_delete signal

I want admins to be notified when certain objects are deleted but I also want to determine which user is performing the delete.Is it possible?This is the code:# models.py # signal to notify admins whe…