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.

2
  • 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. Commented Aug 1, 2021 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 Commented Aug 2, 2021 at 7:32

1 Answer 1

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 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.