C++ 无法使用boost.python导入模块
我正在尝试使用boost.python构建一个简单的程序C++ 无法使用boost.python导入模块,c++,boost,boost-python,C++,Boost,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;
我有以下代码:
//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);
}
运行makegreet.so
时只会出现一些警告(在一些boost文件中重新定义)
当我尝试用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
boostpython需要boostpython
so
文件。当您以多种方式运行python时,可以将其添加到路径中。我正在使用
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH:../ThirdParty/boost_1_52_0/lib/linux64/
boostpython需要boostpython
so
文件。当您以多种方式运行python时,可以将其添加到路径中。我正在使用
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH:../ThirdParty/boost_1_52_0/lib/linux64/
请注意,当您使用gcc链接二进制文件时。将二进制文件传递给链接器的顺序应确保第一个单元(例如,您的对象文件)应使用以下单元(其他对象文件或库)解析。在您的示例中,您正在链接问候语。因此错误:
%.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
请注意,单元greet.o
,它依赖于libboost_python.so
和libpython2.7中定义的符号。因此
排在最后,因此,当gcc的链接器到达它时,它无法再解析未定义的符号。不幸的是,这不是一个错误,因为链接器无法知道您是否需要它(例如,在Python中,libpythonX.Y将在您导入代码之前加载,因此可能会跳过它-您可以从命令行完全转储该库)。因此,默认设置是忽略所有未定义的符号
您可以通过设置两个标志来强制检测未定义的符号,从而更改该行为:
CLinkFlags += -Wl,--unresolved-symbols=report-all
将所有未解析的符号报告为错误,并且:
CLinkFlags += -Wl,--unresolved-symbols=report-all -Wl,--warn-unresolved-symbols
将报告所有未解析的符号,但仍将链接二进制文件。你有其他的选择被警告:这不是你通常想要的。例如,libpythonX.Y
之类的东西从未显式链接,但它们在运行时仍然可用。实际上,您仍然会得到一堆不值得探究的伪未定义引用。最好是修复Makefile,并确保目标代码在库之前出现
要修复您的示例,只需将$^
移动到链接的开始处,如下所示:
gcc $^ ${CLinkFlags} -o $@
编译并运行ldd
后,您应该会看到现在libboost\u python
(以及python
,因为您正在显式链接它)将链接到greet。因此
和加载应该按照您的预期工作。我自己在当地测试过
根据经验,如果您对gcc有未定义的引用,并且您确信它们应该出现在任何链接代码中,请仔细检查顺序
这里是一个完全工作/最小版本的Makefile,它将为您的特定案例执行任务(注意,我们还将运行时路径设置为您的私有boost库,因此您不需要设置LD_library_path
,如其他答案所示-请参阅下面的详细信息):
通过打开库本身,运行时链接器在尝试LD\u library\u路径之前会自动首先查看该库。如果您决定不这样做,则必须按照其他答案设置环境变量LD\u LIBRARY\u PATH
。请注意,当您将二进制文件链接到gcc时。将二进制文件传递给链接器的顺序应确保第一个单元(例如,您的对象文件)应使用以下单元(其他对象文件或库)解析。在您的示例中,您正在链接问候语。因此错误:
%.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
请注意,单元greet.o
,它依赖于libboost_python.so
和libpython2.7中定义的符号。因此
排在最后,因此,当gcc的链接器到达它时,它无法再解析未定义的符号。不幸的是,这不是一个错误,因为链接器无法知道您是否需要它(例如,在Python中,libpythonX.Y将在您导入代码之前加载,因此可能会跳过它-您可以从命令行完全转储该库)。因此,默认设置是忽略所有未定义的符号
您可以通过设置两个标志来强制检测未定义的符号,从而更改该行为:
CLinkFlags += -Wl,--unresolved-symbols=report-all
将所有未解析的符号报告为错误,并且:
CLinkFlags += -Wl,--unresolved-symbols=report-all -Wl,--warn-unresolved-symbols
将报告所有未解析的符号,但仍将链接二进制文件。你有其他的选择被警告:这不是你通常想要的。例如,libpythonX.Y
之类的东西从未显式链接,但它们在运行时仍然可用。实际上,您仍然会得到一堆不值得探究的伪未定义引用。最好是修复Makefile,并确保目标代码在库之前出现
要修复您的示例,只需将$^
移动到链接的开始处,如下所示:
gcc $^ ${CLinkFlags} -o $@
编译并运行ldd
后,您应该会看到现在libboost\u python
(以及python
,因为您正在显式链接它)将链接到greet。因此
和加载应该按照您的预期工作。我自己在当地测试过
根据经验,如果您对gcc有未定义的引用,并且您确信它们应该出现在任何链接代码中,请仔细检查顺序
这里是一个完全工作/最小版本的Makefile,它将为您的特定案例执行任务(注意,我们还将运行时路径设置为您的私有boost库,因此您不需要设置LD_library_path
,如其他答案所示-请参阅下面的详细信息):
通过打开库本身,运行时链接器在尝试LD\u library\u路径之前会自动首先查看该库。如果你