2013-07-16 2 views
1

나는 boost.python을 사용하여 간단한 프로그램을 작성하려고합니다. (일부 부스트 파일 재정의)boost.python을 사용하여 모듈을 가져올 수 없습니다.

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 실행을 실행 :

//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 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

gcc와 바이너리를 연결할 때 order is important에 유의해야한다. 링커에 바이너리를 넘겨주는 순서는 단위 (다른 객체 파일 또는 라이브러리) 뒤에 을 사용하여 첫 번째 단위 (예 : 객체 파일)가 처리되어야하는 순서 여야합니다. 당신의 예에서, 당신은 잘못 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 

공지 사항이 libboost_python.solibpython2.7.so에 정의 된 기호에 따라 단위 greet.o, 마지막으로 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을 설정할 필요가 없습니다). 다른 답변으로 -) 자세한 내용은 아래를 참조하십시오 라이브러리 자체에 setting the runtime 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} $^ 

는 런타임 링커는 자동으로 LD_LIBRARY_PATH을 시도하기 전에 먼저이 보인다. 그렇게하지 않으려면 다른 대답에 표시된대로 환경 변수 LD_LIBRARY_PATH을 설정해야합니다.

+0

감사합니다. 나는 그 명령에 의미가 있다는 것을 전혀 몰랐다. – elyashiv

+0

답변은 훌륭하지만 아직 끝나지 않았습니다. 모든 오류에서 귀하의 답변을 Dr.loves의 답변과 병합하십시오. – elyashiv

+0

자, 링커 자체를 사용하여 어떻게 할 수 있는지를 설명하는 주석을 추가했습니다. –

1

부스트 파이썬은 부스트 ​​파이썬 so 파일이 필요합니다. 파이썬을 다양한 방법으로 실행할 때 경로에 추가 할 수 있습니다. 내가 사용하고있다

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 부스트 비단뱀 있나요? – doctorlove

+0

예. 내가 게시 한 메이크 파일에서 이것을 볼 수 있었다. – 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 
관련 문제