Linking error trying to compile C code embedded with Python - python

I'm trying to import and run this python function inside C code:
import requests
import json
url = 'http://127.0.0.1:5000/'
def verify():
code = input('Show-me the code: ')
r = requests.post(url, data=json.dumps({'code': code}))
return r.json()
Here is the C code:
#include <Python.h>
int main(void){
PyObject *myModuleString, *myModule, *myFunction, *myResult;
Py_Initialize();
myModuleString = PyUnicode_FromString((char*)"verify");
myModule = PyImport_Import(myModuleString);
myFunction = PyObject_GetAttrString(myModule,(char*)"verify");
myResult = PyObject_CallObject(myFunction, NULL);
const char* s = PyUnicode_AsUTF8(myResult);
printf("REPR: %s\n", s);
Py_Finalize();
return 0;
}
Create the object file works fine:
$ gcc -c `python3.7-config --cflags --ldflags` source_code.c
$
But it does not work at the end:
$ gcc source_code.o -o source_code.bin
/usr/bin/ld: source_code.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
The -fPIE argument also does not help:
$ gcc -c `python3.7-config --cflags --ldflags` -fPIE source_code.c
$
$ gcc source_code.o -o source_code.bin
/usr/bin/ld: source_code.o: in function `main':
/home/user/source_code.c:7: undefined reference to `Py_Initialize'
/usr/bin/ld: /home/user/source_code.c:9: undefined reference to `PyUnicode_FromString'
/usr/bin/ld: /home/user/source_code.c:10: undefined reference to `PyImport_Import'
/usr/bin/ld: /home/user/source_code.c:12: undefined reference to `PyObject_GetAttrString'
/usr/bin/ld: /home/user/source_code.c:13: undefined reference to `PyObject_CallObject'
/usr/bin/ld: /home/user/source_code.c:15: undefined reference to `PyUnicode_AsUTF8'
/usr/bin/ld: /home/user/source_code.c:18: undefined reference to `Py_Finalize'
collect2: error: ld returned 1 exit status
How can I define the references to generate the binary file?

I had a similar error. Adding the -no-pie argument to the compile statement worked for me.
You could try this:
gcc -c `python3.7-config --cflags --ldflags` source_code.c -no-pie

Related

C++ Boost + Python: undefined reference to Py_Dealloc

I'm trying to use the Python module on Boost. However, I'm getting an error that I cannot find what to do with.
It seems a missing switch or something, but I really could not find...
Does anyone have a clue?
Thanks!!!
/usr/include/python3.8/object.h|478|undefined reference to `_Py_Dealloc'|
System data:
Using Code::blocks, Python 3.8, Linux Mint, installed Boost by apt-get
Build log:
g++ -Wall -fexceptions -g -I/usr/lib/x86_64-linux-gnu/ -I/usr/include/python3.8/ -I/home/tavares/Downloads/boost/boost_1_77_0/stage/lib -c /home/tavares/Trabalho/pesquisa/softwares/optpipeline/PyOPY/PyOPI/bark.cpp -o obj/Debug/bark.o
g++ -Wall -fexceptions -g -I/usr/lib/x86_64-linux-gnu/ -I/usr/include/python3.8/ -I/home/tavares/Downloads/boost/boost_1_77_0/stage/lib -c /home/tavares/Trabalho/pesquisa/softwares/optpipeline/PyOPY/PyOPI/main.cpp -o obj/Debug/main.o
g++ -L/usr/lib/x86_64-linux-gnu/ -o bin/Debug/PyOPI obj/Debug/bark.o obj/Debug/main.o -lboost_program_options -lboost_system -lboost_python38
/usr/bin/ld: obj/Debug/bark.o: in function `_Py_DECREF':
/usr/include/python3.8/object.h:478: undefined reference to `_Py_Dealloc'
/usr/bin/ld: obj/Debug/bark.o: in function `boost::python::detail::none()':
/usr/local/include/boost/python/detail/none.hpp:16: undefined reference to `_Py_NoneStruct'
/usr/bin/ld: /usr/local/include/boost/python/detail/none.hpp:16: undefined reference to `_Py_NoneStruct'
/usr/bin/ld: obj/Debug/bark.o: in function `boost::python::api::object::object()':
/usr/local/include/boost/python/object_core.hpp:400: undefined reference to `_Py_NoneStruct'
/usr/bin/ld: /usr/lib/x86_64-linux-gnu//libboost_python38.so: undefined reference to `PyExc_ValueError'
/usr/bin/ld: /usr/lib/x86_64-linux-gnu//libboost_python38.so: undefined reference to `PyLong_AsLong'
This is kinda old, but try adding
$(python3.10-config --ldflags --embed)
to the commands at the linking phase.
Your link command becomes something like
g++ -L/usr/lib/x86_64-linux-gnu/ -o bin/Debug/PyOPI obj/Debug/bark.o obj/Debug/main.o -lboost_program_options -lboost_system -lboost_python38
$(python3.10-config --ldflags --embed)
Hope this helps someone.

Embedded python fails to compile on Raspberry Pi

I installed python 3.9.1 on my Raspberry Pi following the instructions here https://www.ramoonus.nl/2020/10/06/how-to-install-python-3-9-on-raspberry-pi/ and set it as the default python interpreter. I got my compiling and linking parameters for embedded Python following the instructions here https://docs.python.org/3.9/extending/embedding.html#compiling-and-linking-under-unix-like-systems
I tried a simple test with the following code (test.c) :
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
Py_Finalize();
PyMem_RawFree(program);
return 0;
}
and then
gcc -I/usr/local/opt/python-3.9.1/include/python3.9 -I/usr/local/opt/python-3.9.1/include/python3.9 -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -c test.c -o test.o
and
gcc -L/usr/local/opt/python-3.9.1/lib/python3.9/config-3.9-arm-linux-gnueabihf -L/usr/local/opt/python-3.9.1/lib -lcrypt -lpthread -ldl -lutil -lm -o test.o
and got
/usr/lib/gcc/arm-linux-gnueabihf/4.9/../../../arm-linux-gnueabihf/crt1.o: In function '_start': /build/glibc-P1SmLh/glibc-2.19/csu/../ports/sysdeps/arm/start.S:119: undefined reference to 'main' collect2: error: ld returned 1 exit status
Trying to compile the example at https://docs.python.org/3.9/extending/embedding.html#pure-embedding throws the same error. What could the problem be?
Edit:
After Expolarity's comment I changed the linker command to:
gcc test.o -L/usr/local/opt/python-3.9.1/lib/python3.9/config-3.9-arm-linux-gnueabihf -L/usr/local/opt/python-3.9.1/lib -lcrypt -lpthread -ldl -lutil -lm -o test
which seems to have worked but threw me a bunch of other errors:
test.o: In function main': /home/pi/Downloads/test.c:6: undefined reference to Py_DecodeLocale'
/home/pi/Downloads/test.c:11: undefined reference to Py_SetProgramName' /home/pi/Downloads/test.c:12: undefined reference to Py_Initialize'
/home/pi/Downloads/test.c:13: undefined reference to PyRun_SimpleStringFlags' /home/pi/Downloads/test.c:15: undefined reference to Py_Finalize'
/home/pi/Downloads/test.c:16: undefined reference to `PyMem_RawFree'
collect2: error: ld returned 1 exit status
This seems more serious. Any ideas?
After tttapa's answer over here it finally worked by adjusting the linker command as so:
gcc test.o -L/usr/local/opt/python-3.9.1/lib/python3.9/config-3.9-arm-linux-gnueabihf -L/usr/local/opt/python-3.9.1/lib -lcrypt -lpthread -ldl -lutil -lm -lpython3.9 -o test
Edit: Expolarity also answered correctly just after tttapa. Thanks a lot everyone!

Reference undefined to functions in python-dev header

I'm trying to embedding some Python code into C; It's the first time I do a thing like that.
Here is the simple code of my first attempt copied by a guide on internet:
#include <Python.h>
void exec_pycode(const char* code)
{
Py_Initialize();
PyRun_SimpleString(code);
Py_Finalize();
}
int main(int argc, char **argv) {
exec_pycode(argv[1]);
return 0;
}
So I've installed python3.4-dev package.
Then for having info for the linker I typed:
pkg-config --cflags --libs python3
Then I tried to compile my code:
gcc -std=c99 -o main -I /usr/local/include/python3.4m -L /usr/local/lib -lpython3.4m main.c
(according the command before)
but this is the result:
/tmp/ccJFmdcr.o: in function "exec_pycode":
main.c:(.text+0xd): reference undefined to "Py_Initialize"
main.c:(.text+0x1e): reference undefined to "PyRun_SimpleStringFlags"
main.c:(.text+0x23): reference undefined to "Py_Finalize"
collect2: error: ld returned 1 exit status
It would seem that there is a problem with linking phase, but I can't understend where is the problem seeing that i've passed to the linker the exact paths of the header and of the library. How can I solve that problem?
Try reordering your compilation command, such that all linking options are specified after your C source files:
gcc -std=c99 -o main -I /usr/local/include/python3.4m main.c \
-L /usr/local/lib -lpython3.4m

Python C binding error

I have written a Python API in C code and saved the file as foo.c.
Code:
#include <Python.h>
#include <stdio.h>
static PyObject *foo_add(PyObject *self, PyObject *args)
{
int a;
int b;
if (!PyArg_ParseTuple(args, "ii", &a, &b))
{
return NULL;
}
return Py_BuildValue("i", a + b);
}
static PyMethodDef foo_methods[] = {
{ "add", (PyCFunction)foo_add, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
PyMODINIT_FUNC initfoo()
{
Py_InitModule3("foo", foo_methods, "My first extension module.");
}
When i try to compile using the below mentioned command i am getting compilation error.
Command: gcc -shared -I/usr/include/python2.7 foo.c -o foo.so
Error:
gcc -shared -I/usr/include/python2.7 foo.c -o foo.so
/usr/bin/ld: /tmp/ccd6XiZp.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp/ccd6XiZp.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
If i give compilation command with "-c" option, its getting compiled successfully and created the object file foo.so (This is the executable file).
I have to create a object file (without using -c option in compilation command) and import them in Python shell to verify it.
Please let me know what am i doing wrong here.
In your compilation flags you should include -fPIC to compile as position independent code. This is required for dynamically linked libraries.
e.g.
gcc -c -fPIC foo.c -o foo.o
gcc -shared foo.o -o foo
or in a single step
gcc -shared -fPIC foo.c -o foo.so

Python extension: symbol(s) not found for architecture x86_64 error

I want to write a python extension in c. I work on Mac, I took a code from here:
#include <Python.h>
static PyObject* say_hello(PyObject* self, PyObject* args)
{
const char* name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
printf("Hello %s!\n", name);
Py_RETURN_NONE;
}
static PyMethodDef HelloMethods[] =
{
{"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
inithello(void)
{
(void) Py_InitModule("hello", HelloMethods);
}
I compile it:
gcc -c -o py_module.o py_module.c -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/
gcc -o py_module py_module.o -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/ -lm
But I get this error:
Undefined symbols for architecture x86_64:
"_PyArg_ParseTuple", referenced from:
_say_hello in py_module.o
"_Py_InitModule4_64", referenced from:
_inithello in py_module.o
"__Py_NoneStruct", referenced from:
_say_hello in py_module.o
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [py_module] Error 1
How comes python doesn't support X86_64 architecture?
Two things:
You need to link your extension as a shared object (you're attempting to link an executable, which is why the linker is looking for main());
You need to link against the Python static library (-lpython).
Query the python env path with these commands:
$python-config --includes
-I/usr/include/python2.6 -I/usr/include/python2.6
$python-config --ldflags
-lpthread -ldl -lutil -lm -lpython2.6
generate .o file:
$ g++ -fPIC -c -I/usr/include/python2.6 -I/usr/include/python2.6 xx.cpp
generate .so file:
g++ -shared xx.o -o xx.so
Thanks to #NPE #glglgl and anatoly here is my Makefile:
DIR=/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/
CC=gcc
CFLAGS=-I$(DIR)
ODIR=.
LIBS_DIR=/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/
LIBS=-lpython2.7
_DEPS =
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = py_module.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
py_module: $(OBJ)
gcc -shared $^ $(CFLAGS) -I$(LIBS_DIR) $(LIBS) -o $#
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
makefile template had been taken from here.
In order to find the paths, one may use python-config --ldflags
and python-config --includes

Categories

Resources