0

I am trying to compile the example C application embedding Python (from here https://docs.python.org/3.8/extending/embedding.html)

#define PY_SSIZE_T_CLEAN
#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");
    if (Py_FinalizeEx() < 0) {
        exit(120);
    }
    PyMem_RawFree(program);
    return 0;
}

I'm using gcc options generated by python3.8-config. Thus, compile and link are done as follows:

gcc $(python3.8-config --cflags) -c embePy.c -o embePy.o

gcc $(python3.8-config --ldflags) -o embePy.o

Compiling goes smoothly, whereas linking throws an error:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status

Just in case:

$ /usr/bin/python3-config --cflags
-I/usr/include/python3.8 -I/usr/include/python3.8  -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.8-CoVRmP/python3.8-3.8.10=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O3 -Wall

$ /usr/bin/python3-config --ldflags
-L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm 

I don't have experience with manual control of gcc's options, all what I've done was compilation from inside IDE's with automatically set flags. Can anybody help me to identify the problem? Thank you.

  • I was not able to repeat that error, I got the dreaded "relocation R_X86_64_32" one. I know what *that* means and was able to get it to compile (removing the no-pie specs). But what I stumbled upon was the lack of ` -lpython3.8` in the output of `$(python3.8-config --ldflags)` which is needed. You should also use `gcc $(python3.8-config --ldflags) embePy.o -o embPy` to avoid overwriting `embePy.o`. That got it all compiled and running `./embPy` returned the date as expected. – deamentiaemundi Aug 01 '21 at 22:34
  • @deamentiaemundi thank you for the comment. I've tried to compile with `gcc $(python3.8-config --cflags) -fPIE -c embePy.c -o embePy.o` to avoid "relocation R_X86_64_32", then linking with `gcc $(python3.8-config --ldflags) -lpython3.8 embePy.o -o embPy`. Or, in one command: `gcc $(python3.8-config --cflags) -fPIE -o embePy $(python3.8-config --ldflags) -lpython3.8 ./embePy.c`. In both cases I get "undefined references" to each of Py... functions in the source. Adding/removing `-lpython3.8` doesn't change anything, actually – Artem Plyusnin Aug 02 '21 at 07:32

1 Answers1

0

I solved the problem, thank @deamentiaemundi and the post from here: https://stackoverflow.com/a/27672776/9256844

To avoid "relocation R_X86_64_32", compile with -fPIE:

gcc $(python3.8-config --cflags) -fPIE -c embePy.c -o embePy.o

To link against the Python libs, I had to put my object file before the python's flags AND manually add -lpython3.8:

gcc embePy.o $(python3.8-config --ldflags) -lpython3.8 -o embePy

Looks like my version of Python mistakenly outputs duplicated flag -lm instead of -lpython3.8 (Python 3.8.10):

$ python3.8-config --ldflags
-L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -L/usr/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm