pythongccanacondaconda

undefined reference to `Py_Initialize' when build a simple demo.c on a Linux conda environment


I am testing of running a Python thread in a c program with a simple example like the below

# demo.py
import time

for i in range(1, 101):
    print(i)
    time.sleep(0.1)
// demo.c
#include <Python.h>
#include <pthread.h>
#include <stdio.h>

void *run_python_script(void *arg) {
    Py_Initialize();

    if (!Py_IsInitialized()) {
        fprintf(stderr, "Python initialization failed\n");
        return NULL;
    }

    FILE *fp = fopen("demo.py", "r");
    if (fp == NULL) {
        fprintf(stderr, "Failed to open demo.py\n");
        Py_Finalize();
        return NULL;
    }

    PyRun_SimpleFile(fp, "demo.py");
    fclose(fp);
    Py_Finalize();

    return NULL;
}

int main() {
    pthread_t python_thread;

    if (pthread_create(&python_thread, NULL, run_python_script, NULL) != 0) {
        fprintf(stderr, "Failed to create thread\n");
        return 1;
    }

    pthread_join(python_thread, NULL);
    printf("Python thread has finished. Exiting program.\n");
    return 0;
}

Then I build the above code with the following command

gcc demo.c -o demo -lpthread -I$(python3-config --includes) $(python3-config --ldflags) $(python3-config --cflags)

Then I get the following error:

/usr/bin/ld: /tmp/ccsHQpZ3.o: in function `run_python_script':
demo.c:(.text.run_python_script+0x7): undefined reference to `Py_Initialize'
/usr/bin/ld: demo.c:(.text.run_python_script+0xd): undefined reference to `Py_IsInitialized'
/usr/bin/ld: demo.c:(.text.run_python_script+0x41): undefined reference to `PyRun_SimpleFileExFlags'
/usr/bin/ld: demo.c:(.text.run_python_script+0x50): undefined reference to `Py_Finalize'
/usr/bin/ld: demo.c:(.text.run_python_script+0xab): undefined reference to `Py_Finalize'
collect2: error: ld returned 1 exit status

The python library do exists,


python3-config --ldflags
-L/home/henry/anaconda3/lib/python3.9/config-3.9-x86_64-linux-gnu -L/home/henry/anaconda3/lib  -lcrypt -lpthread -ldl  -lutil -lm -lm


ls -1 ~/anaconda3/lib | grep python
libpython3.9.so
libpython3.9.so.1.0
libpython3.so
python3.9

I have no idea about is link error.


Solution

  • You need to pass --embed to python3-config because you are embedding a Python interpreter in your program. Observe the difference:

    $ python3-config --ldflags
    -L/usr/lib/python3.10/config-3.10-x86_64-linux-gnu 
    -L/usr/lib/x86_64-linux-gnu  -lcrypt -ldl  -lm -lm
    
    $ python3-config --embed --ldflags
    -L/usr/lib/python3.10/config-3.10-x86_64-linux-gnu 
    -L/usr/lib/x86_64-linux-gnu -lpython3.10 -lcrypt -ldl  -lm -lm