2013-07-16 171 views
1

我正在嘗試使用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); 
} 

和follwing 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,[email protected] -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 [email protected] $^ 

%.o: %.cpp 
    ${CC} ${CFLAGS} ${CInc} $^ 

運行make greet.so運行,只需幾個警告(重新定義一些提振文件)。

當我嘗試導入模塊中的蟒蛇,我得到如下:

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) 
+0

如果你在Linux上,你是否也可以粘貼'ldd greet.so'的輸出?這是否顯示你的boost_python庫鏈接? –

+0

@AndréAnjos補充說。 – elyashiv

+0

'libboost_python'在哪裏?它沒有鏈接,因此,你有缺失的符號。確保您的編譯按預期工作。 –

回答

2

請注意:order is important當你正在用gcc鏈接二進制文件。將二進制文件傳遞給鏈接程序的順序應使得第一個單元(例如,您的目標文件)應使用以下單元(其他目標文件或庫)解析。在你的榜樣,你是錯誤鏈接greet.so

%.so: %.o 
    gcc ${CLinkFlags} -o [email protected] $^ 

這將產生一個編譯行是這樣的:

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.solibpython2.7.so定義的符號是最後的,因此,當gcc的鏈接程序到達它時,它不能再解析未定義的符號。不幸的是,這不是一個錯誤,因爲鏈接器無法知道你是否需要它(例如,在Python中,libpythonX.Y會在您導入代碼之前加載,因此可能會跳過 - 您可以轉儲來自你的命令行的庫)。所以,默認是忽略所有未定義的符號。

您可以通過設置幾個標誌強制未定義的符號檢測改變這種行爲:

CLinkFlags += -Wl,--unresolved-symbols=report-all 

將報告所有未解決的符號,錯誤和:

CLinkFlags += -Wl,--unresolved-symbols=report-all -Wl,--warn-unresolved-symbols 

將報告所有未解決的符號,但仍然會鏈接二進制文件。您有其他選項解釋on this SO thread被警告:這通常不是你想要的。例如libpythonX.Y這樣的東西從來沒有明確鏈接,但它們在運行時仍然可用。在實踐中,你仍然會得到一堆不值得追求的未定義引用。最好的辦法是修復你的Makefile,並確保你的目標代碼在之前來到庫。

要解決你的榜樣,只是移動$^開始的鏈接,如:

gcc $^ ${CLinkFlags} -o [email protected] 

後您編譯和運行ldd,你應該看到現在libboost_python(和python因爲你是明確鏈接它)將鏈接到greet.so和加載應該如你所期望的那樣工作。我在本地測試它。

作爲一個經驗法則,如果您有未定義的gcc引用,並且您確信它們應該出現在任何鏈接的代碼中,請仔細檢查該訂單。

這裏是一個完全工作/最小版本的Makefile,它將爲您的特定情況完成工作(請注意,我們也將運行時路徑設置爲您的私有增強庫,因此不需要按照指示設置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,[email protected] -Wl,-rpath,${BOOST_LIB_LOCATION} -L${BOOST_LIB_LOCATION} -l${BOOST_LIB_FILE} 

greet.so: greet.o 

%.so: %.o 
    gcc $^ ${CLinkFlags} -o [email protected] 

%.o: %.cpp 
    ${CC} ${CFLAGS} ${CInc} $^ 

通過setting the runtime path在庫本身,運行時鏈接會自動嘗試LD_LIBRARY_PATH之前,首先看那裏。如果您決定不這樣做,那麼您必須設置環境變量LD_LIBRARY_PATH,如其他答案所示。

+0

謝謝。我不知道訂單是否有意義。 – elyashiv

+0

你的回答很好,但它還沒有結束。將你的答案與Doctorloves合併,從所有的錯誤中解脫出來。 – elyashiv

+0

好吧,我剛剛添加了一條評論,指出如何使用鏈接器本身來做到這一點。 –

1

升壓蟒需要升壓蟒蛇so文件。當你以各種方式運行python時,你可以將它添加到你的路徑中。我使用

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH:../ThirdParty/boost_1_52_0/lib/linux64/ 
+0

它似乎沒有工作。我運行'export LD_LIBRARY_PATH =。:$ LD_LIBRARY_PATH:〜/ boost_1_54_0/stage/lib',並得到相同的錯誤。我使用錯誤的目錄? – elyashiv

+0

我拿它/ boost_1_54_0/stage/lib有boost python麼? – doctorlove

+0

是的。你可以在我發佈的makefile上看到這個。 – elyashiv

0

試試這些命令。這些爲我工作。

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