无法使用boost.python导入模块
cannot import module using boost.python
我正在尝试使用boost.python构建一个简单的程序。
我有以下代码:
//greet.cpp
#include <iostream>
#include <boost/python.hpp>
void greet()
{
std::cout << "hello world!" << std::endl;
}
BOOST_PYTHON_MODULE(greet)
{
using namespace boost::python;
def("greet", greet);
}
以及以下makefile
:
PYTHON_VERSION := 2.7
PYTHON_INC := /usr/include/python$(PYTHON_VERSION)
PYTHON_LIB_LOCATION := /usr/lib/python${PYTHON_VERSION}
PYTHON_LIB_FILE := python${PYTHON_VERSION}
BOOST_INC := ~/boost_1_54_0
BOOST_LIB_LOCATION := /home/elyashiv/boost_1_54_0/stage/lib
BOOST_LIB_FILE := boost_python
CC := gcc
CFLAGS := -c -fPIC
CInc := -I ${BOOST_INC} -I ${PYTHON_INC}
CLinkFlags = -shared -Wl,-soname,$@ -L${BOOST_LIB_LOCATION} -l${BOOST_LIB_FILE} -L${PYTHON_LIB_LOCATION} -l${PYTHON_LIB_FILE}
greet.o: greet.cpp
%.so: %.o
gcc ${CLinkFlags} -o $@ $^
%.o: %.cpp
${CC} ${CFLAGS} ${CInc} $^
运行make greet.so
时只有几个警告(在某些提升文件中进行了重新定义)。
当我尝试在python中导入模块时,我会得到以下信息:
Python 2.7.3 (default, Apr 10 2013, 05:46:21)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import greet
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: ./greet.so: undefined symbol: _ZNK5boost6python7objects21py_function_impl_base9max_arityEv
我做错了什么?如何解决?
编辑
ldd greet.so
:的输出
linux-gate.so.1 => (0x001ee000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x0055d000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x0058e000)
/lib/ld-linux.so.2 (0x003a2000)
请注意,当您使用gcc链接二进制文件时,顺序很重要。将二进制文件传递到链接器的顺序应确保第一个单元(例如,对象文件)应使用以下单元(其他对象文件或库)进行解析。在您的示例中,您错误地链接了greet.so
:
%.so: %.o
gcc ${CLinkFlags} -o $@ $^
这将生成这样的编译行:
gcc -shared -Wl,-soname,greet.so -L/usr/lib -lboost_python -L/usr/lib/python2.7 -lpython2.7 -o greet.so greet.o
请注意,依赖于libboost_python.so
和libpython2.7.so
中定义的符号的单元greet.o
排在最后,因此,当gcc的链接器到达它时,它无法再解析未定义的符号。不幸的是,这不是一个错误,因为链接器无法知道你是否想要这个(例如,在Python中,libpythonX.Y将在你导入代码之前加载,因此它可能会被跳过-你可以从命令行完全转储该库)。因此,默认情况是忽略所有未定义的符号。
您可以通过设置几个标志来强制检测未定义的符号来改变这种行为:
CLinkFlags += -Wl,--unresolved-symbols=report-all
将所有未解决的符号报告为错误,并:
CLinkFlags += -Wl,--unresolved-symbols=report-all -Wl,--warn-unresolved-symbols
将报告所有未解析的符号,但仍将链接二进制。您在这个SO线程中解释了其他选项请注意:这不是您通常想要的。例如,像libpythonX.Y
这样的东西从未显式链接,但它们在运行时仍然可用。在实践中,你仍然会得到一堆不值得去追求的虚假的未定义引用。最好的方法是修复您的Makefile,并确保您的对象代码早于库。
要修复您的示例,只需将$^
移动到链接的开始,如:
gcc $^ ${CLinkFlags} -o $@
在编译并运行ldd
之后,您应该看到现在libboost_python
(以及python
,因为您显式地链接它)将与greet.so
链接,并且加载应该如您所期望的那样工作。我自己在当地测试过。
根据经验,如果您对gcc有未定义的引用,并且您确信它们应该出现在任何链接的代码中,请仔细检查顺序。
以下是Makefile的一个完整工作/最小版本,它将为您的特定案例完成工作(请注意,我们还设置了您的私有boost库的运行时路径,因此您不需要像其他答案所示那样设置LD_LIBRARY_PATH
-请参阅下面的详细信息):
PYTHON_VERSION := 2.7
PYTHON_INC := /usr/include/python$(PYTHON_VERSION)
BOOST_INC := /home/elyashiv/boost_1_54_0
BOOST_LIB_LOCATION := /home/elyashiv/boost_1_54_0/stage/lib
BOOST_LIB_FILE := boost_python
CC := gcc
CFLAGS := -c -fPIC
CInc := -I${BOOST_INC} -I${PYTHON_INC}
CLinkFlags = -shared -Wl,-soname,$@ -Wl,-rpath,${BOOST_LIB_LOCATION} -L${BOOST_LIB_LOCATION} -l${BOOST_LIB_FILE}
greet.so: greet.o
%.so: %.o
gcc $^ ${CLinkFlags} -o $@
%.o: %.cpp
${CC} ${CFLAGS} ${CInc} $^
通过在库本身上设置运行时路径,运行时链接器会在尝试LD_LIBRARY_PATH
之前先自动查找。如果您决定不这样做,则必须设置环境变量LD_LIBRARY_PATH
,如其他答案所示。
Boost python需要Boost python so
文件。当您以各种方式运行python时,您可以将其添加到您的路径中。我正在使用
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH:../ThirdParty/boost_1_52_0/lib/linux64/
试试这些命令。这些对我有用。
g++ -c -I/usr/include/python2.7 -fPIC hello.cpp -o hello.o
g++ -shared -Wl,-soname,"hello.so" -L/usr/local/lib hello.o -lboost_python -fPIC -o hello.so
- Python 3.8 不能与 Pybind11 一起导入 [Windows]
- 在 python 模块中导入子模块时PyImport_Import失败
- 在从Qt调用的Python脚本中导入OpenCV崩溃
- 编译boost_python扩展无法在 python 2.7 中导入
- Python 3.8:运行外部C++代码:无法导入模块
- C++ #include<XXX.h>相当于 Python 导入的 XXX 作为 X
- 如何将 Cython 生成的模块从 python 导入到 C/C++ 主文件?(C/C++编程)
- Python - 导入 c++ 模块接口 - 无法打开共享对象文件
- 提升 Python 导入失败,未定义包装类的符号
- 如何处理python导入模块中c++断言导致的Celery WorkerLostError
- Boost Python :导入模块时遇到问题
- 从 boost python 导入依赖的 python 库
- 无法使用boost.python导入模块
- 从自定义构建的Python导入自定义模块失败
- Boost Python导入一个带有std::vectors作为参数的c++函数
- c++ Python导入类;调用方法
- 由python导入的python错误
- Python 3.x - 导入密码化 C++ 代码时未定义的符号
- MAC雪豹端口上的Boost python导入错误
- 从您无法控制且无权访问的线程中释放 Python 导入锁