【问题标题】:Python C_API with GCC - Python.h not found带有 GCC 的 Python C_API - 未找到 Python.h
【发布时间】:2021-11-29 05:28:45
【问题描述】:

我正在使用下面显示的程序在 Ubuntu 18.04 上使用 Python 3.8 测试 Python C_API。我曾尝试使用 Clang-10 和 GCC 7.5 进行编译,但在这两种情况下编译器都无法找到 Python.h。

当我运行这个字符串时:

sudo gcc -v -shared -fPIC -l /usr/include/python3.8 -I/usr/lib -I/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -I/usr/lib/python3.8 -lpython3.8 -lcrypt -lpthread -ldl  -lutil -lm  -Wall -o Python_Math.o Python_Math.c

我得到“Python_Math.c:2:10:致命错误:Python.h:没有这样的文件或目录#include

我把字符串改成这样:

sudo gcc Python_Math.c -o Python_Math.o -v -shared -fPIC -l/usr/lib -l/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -I/usr/include/python3.8 -l/usr/lib/python3.8 -lpython3.8 -lcrypt -lpthread -ldl  -lutil -lm -Wall

我得到:

/usr/bin/ld: 找不到 -l/usr/lib /usr/bin/ld: 找不到 -l/usr/lib/python3.8/config-3.8-x86_64-linux-gnu /usr/bin/ld: 找不到 -l/usr/lib/python3.8

所以我将字符串简化为:

sudo gcc Python_Math.c -o Python_Math.o -v -shared -fPIC -I/usr/include/python3.8 -lpython3.8 -lcrypt -lpthread -ldl  -lutil -lm -Wall

现在程序可以编译和链接,但是当我在 Python_Math.o 上运行“nm”时,它会将所有导入的符号(包括 Py_Initialize)显示为未定义。

最后我将字符串简化为:

sudo gcc Python_Math.c -o Python_Math.o -v -shared -fPIC -I/usr/include/python3.8 -lpython3.8 -Wall

它再次编译和链接,但 nm 仍将符号显示为“未定义”。

如果我将上面字符串中的“I”更改为 -L/usr/include/python3.8 的“L”,我再次得到“Python.h”未找到,并且一条消息重新搜索包含的路径,其中在路径中显示 usr/include。

#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/7/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

问题似乎出在 Python.h 的路径上。 Locate 说 Python.h 位于 /usr/include/python3.8/Python.h。

Embedding Python in C, linking fails with undefined reference to `Py_Initialize' 的一个问题说要在 Ubuntu 20.04 上添加“嵌入”,但我还没有找到一种方法可以在 Ubuntu 18.04 上使用。

这是完整的程序:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

int Lib_Math(char* module_name, char* fn_name, double value_in)
{
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;
    int i = 0;

    Py_Initialize();
    pName = PyUnicode_DecodeFSDefault(module_name);

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, fn_name);
        /* pFunc is a new reference */

        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(value_in);
            pValue = PyLong_FromDouble(value_in);

            if (!pValue) {
                Py_DECREF(pArgs);
                Py_DECREF(pModule);
                fprintf(stderr, "Cannot convert argument\n");
                return 1;
            }

            /* pValue reference stolen here: */
            PyTuple_SetItem(pArgs, i, pValue);

            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("Result of call: %ld\n", PyLong_AsLong(pValue));
                Py_DECREF(pValue);
            }
else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", fn_name);
        }    
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", module_name);
        return 1;
    }
    if (Py_FinalizeEx() < 0) {
        return 120;
    }
    return 0;
}

感谢您在获取正确链接选项方面提供的任何帮助。

【问题讨论】:

  • 符号将由 libpython.so 提供,使用 ldd 查看依赖关系,或者您可以针对静态版本强制链接,参见例如stackoverflow.com/q/48796014/5769463
  • Locate libpython.so 什么也没找到,但 libpython3.8.so 找到了,所以我会处理它。

标签: python c gcc python-c-api


【解决方案1】:

您搞砸了IL/l 选项。正确的语法是:

gcc -v -shared -fPIC \
    -I/usr/include/python3.8 \
    -L/usr/lib -L/usr/lib/python3.8 \
    -lpython3.8 -lcrypt -lpthread -ldl -lutil -lm \
    -Wall -o Python_Math.so Python_Math.c

-I 用于包含目录,-L 用于库目录,-l 用于库文件。

编译器和链接器选项可以通过运行命令获得:

python3.8-config --includes
  -I/usr/include/python3.8 -I/usr/include/python3.8

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 

您将模块编译为共享库对象*.so,因此Py_Initialize 之类的对象将在运行时可用。

【讨论】:

  • 您的字符串已编译,但当我在 Ubuntu 中执行 nm Python_Math.o 时,Python.h 中的所有符号仍显示为“未定义”。
  • 在详细版本中 /usr/include/python3.8 显示为“包含路径”部分中的第一个条目,因此 GCC 搜索该文件夹,但我很困惑为什么符号显示为“未定义。”
  • 我在 libpython3.8 上运行了“nm”,缺少的符号在那里。现在只是链接它。
猜你喜欢
  • 1970-01-01
  • 2012-01-07
  • 2014-03-17
  • 2016-09-17
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
  • 2015-05-13
相关资源
最近更新 更多