【发布时间】: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