삽질記
[삽질記] luabind를 사용하여 루아에서 C++ 코드 호출하기
와신상담
2011. 1. 30. 19:29
luabind는 C++와 루아를 바인딩할 때 도움을 주는 라이브러리이다. 여기서는 luabind에 대한 자세한 설명은 생략하고 luabind 문서에 있는 hello world 프로그램을 작동시키기까지 겪은 일을 정리해 보겠다.
1. luabind 설치
문서에는 bjam을 사용하여 직접 빌드하는 방법이 나와 있지만 귀찮으니 시냅틱 패키지 관리자를 사용하여 설치하기로 하였다.
기본 저장소(main)에는 luabind가 없고 저장소 설정에서 universe 저장소를 체크해야 luabind를 찾을 수 있다
.
luabind로 찾으면 libluabind-dbg, libluabind-dev, libluabind-doc, libluabind-examples, libluabind0.9.0이라는 패키지들이 검색되는데, 모두 설치하였다(의존성이 있는 boost나 lua 관련 패키지들도 모두 설치).
설치가 끝나고 lua를 실행해보니, 'lua'가 없단다.--;
luabind를 설치하면 알아서 깔릴 줄 알았더니 아니었다.
2. lua 설치
역시 시냅틱으로 lua를 설치했다(lua5.1과 lua5.1-doc 설치).
설치 후 lua를 실행시켜 보니, 이번에는 lua shell이 떴다.
3. Hello world 코드 작성 및 컴파일
이제 문서에 나온 Hello world 코드를 작성해야 하는데, 아까 깐 패키지 중에 libluabind-examples라는 이름이 왠지 수상하여 살펴보니, 예제 코드가 포함되어 있었다. 이로써 타이핑할 수고는 덜 수 있었다.
퍼미션 문제가 있으니 Hello world 코드를 홈 디렉터리로 복사하고 make를 실행하였다.
예상대로(--;) 실패한다. 친절한(?) 에러 메시지를 따라서 Makefile에 -fPIC를 추가하고 다시 make를 실행했다.
이번에는 성공했다. hello_world.so라는 파일(shared library)이 생겼다.
4. lua shell에서 Hello world 불러오기
lua shell을 실행한 후, 문서에 나온대로 따라해 봤다
(문서에는 'hello_world.dll'가 나와 있지만 리눅스이므로 'hello_world.so'를 사용했다.)
역시나 바로 되는 일은 없다. --;
여기가 가장 고생한 부분이다. 여기 저기 검색하며 뒤져보다가 최근 버전의 lua에서는 loadlib() 대신 package.loadlib()를 쓰는 것으로 바뀌었다는 내용을 보았다(링크는 잊어버렸다).
어쨌든 package.loadlib()로 바꿔서 시도해봤다.
또 안된다. --; 대신 에러 메시지는 달라졌다. 여기 저기 뒤져봤지만, 해결책은 찾지 못했다.
거의 포기하려다가 혹시나 하는 마음으로 so 파일의 경로에 './'를 추가해 봤다.
드디어 성공이다! 이거 하나 띄우려고 며칠을 고생했던가... 젠장, 문서에 몇 글자만 고쳐져 있었으면 이렇게 고생을 안 했을텐데.. 루아에 대해 전혀 모른 상태여서 더 어려운 점도 있었다.
어쨌든 이번 일로 얻은 교훈은 있다.
(추가)
이 글을 쓰면서 examples/hello_world/README 파일을 열어 보았더니, 거기에는 다음과 같은 내용이 있는 게 아닌가! 이 파일을 열어 보았다면 한 번의 삽질은 줄일 수 있었을 텐데, 가까운 곳을 찾지는 않고 먼 곳을 뒤지고 있었던 것이다.
* 목표 : http://www.rasterbar.com/products/luabind/docs.html의 5.1 Hello world를 실행하기
* 환경 : ubuntu 10.10 x86_64(Live)
* 환경 : ubuntu 10.10 x86_64(Live)
1. luabind 설치
문서에는 bjam을 사용하여 직접 빌드하는 방법이 나와 있지만 귀찮으니 시냅틱 패키지 관리자를 사용하여 설치하기로 하였다.
기본 저장소(main)에는 luabind가 없고 저장소 설정에서 universe 저장소를 체크해야 luabind를 찾을 수 있다
.
luabind로 찾으면 libluabind-dbg, libluabind-dev, libluabind-doc, libluabind-examples, libluabind0.9.0이라는 패키지들이 검색되는데, 모두 설치하였다(의존성이 있는 boost나 lua 관련 패키지들도 모두 설치).
설치가 끝나고 lua를 실행해보니, 'lua'가 없단다.--;
ubuntu@ubuntu:~$ lua
The program 'lua' can be found in the following packages:
* lua5.1
* lua40
Try: sudo apt-get install <selected package>
ubuntu@ubuntu:~$
The program 'lua' can be found in the following packages:
* lua5.1
* lua40
Try: sudo apt-get install <selected package>
ubuntu@ubuntu:~$
luabind를 설치하면 알아서 깔릴 줄 알았더니 아니었다.
2. lua 설치
역시 시냅틱으로 lua를 설치했다(lua5.1과 lua5.1-doc 설치).
설치 후 lua를 실행시켜 보니, 이번에는 lua shell이 떴다.
ubuntu@ubuntu:~$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
>
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
>
3. Hello world 코드 작성 및 컴파일
이제 문서에 나온 Hello world 코드를 작성해야 하는데, 아까 깐 패키지 중에 libluabind-examples라는 이름이 왠지 수상하여 살펴보니, 예제 코드가 포함되어 있었다. 이로써 타이핑할 수고는 덜 수 있었다.
ubuntu@ubuntu:~$ dpkg -L libluabind-examples
...
/usr/share/doc/libluabind-examples/examples/hello_world
/usr/share/doc/libluabind-examples/examples/hello_world/hello_world.cpp
/usr/share/doc/libluabind-examples/examples/hello_world/README
/usr/share/doc/libluabind-examples/examples/hello_world/Makefile
...
ubuntu@ubuntu:~$
...
/usr/share/doc/libluabind-examples/examples/hello_world
/usr/share/doc/libluabind-examples/examples/hello_world/hello_world.cpp
/usr/share/doc/libluabind-examples/examples/hello_world/README
/usr/share/doc/libluabind-examples/examples/hello_world/Makefile
...
ubuntu@ubuntu:~$
퍼미션 문제가 있으니 Hello world 코드를 홈 디렉터리로 복사하고 make를 실행하였다.
ubuntu@ubuntu:~/hello_world$ make
g++ -shared hello_world.cpp -o hello_world.so -I/sw/include -L/sw/lib \
-I/usr/include/lua5.1 -I/usr/include/boost \
-llua5.1 -lluabind
/usr/bin/ld: /tmp/ccBd0u3H.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp/ccBd0u3H.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [helloworld_test] Error 1
ubuntu@ubuntu:~/hello_world$
g++ -shared hello_world.cpp -o hello_world.so -I/sw/include -L/sw/lib \
-I/usr/include/lua5.1 -I/usr/include/boost \
-llua5.1 -lluabind
/usr/bin/ld: /tmp/ccBd0u3H.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp/ccBd0u3H.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [helloworld_test] Error 1
ubuntu@ubuntu:~/hello_world$
예상대로(--;) 실패한다. 친절한(?) 에러 메시지를 따라서 Makefile에 -fPIC를 추가하고 다시 make를 실행했다.
all: helloworld_test
# if using fink on darwin
# you need these additional flags
CPPFLAGS = -I/sw/include -L/sw/lib -fPIC
helloworld_test: hello_world.cpp
$(CXX) -shared hello_world.cpp -o hello_world.so $(CPPFLAGS) \
-I/usr/include/lua5.1 -I/usr/include/boost \
-llua5.1 -lluabind
clean:
rm -f helloworld *.o *~
# if using fink on darwin
# you need these additional flags
CPPFLAGS = -I/sw/include -L/sw/lib -fPIC
helloworld_test: hello_world.cpp
$(CXX) -shared hello_world.cpp -o hello_world.so $(CPPFLAGS) \
-I/usr/include/lua5.1 -I/usr/include/boost \
-llua5.1 -lluabind
clean:
rm -f helloworld *.o *~
이번에는 성공했다. hello_world.so라는 파일(shared library)이 생겼다.
4. lua shell에서 Hello world 불러오기
lua shell을 실행한 후, 문서에 나온대로 따라해 봤다
(문서에는 'hello_world.dll'가 나와 있지만 리눅스이므로 'hello_world.so'를 사용했다.)
ubuntu@ubuntu:~/hello_world$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> loadlib('hello_world.so', 'init')()
stdin:1: attempt to call global 'loadlib' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
>
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> loadlib('hello_world.so', 'init')()
stdin:1: attempt to call global 'loadlib' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
>
역시나 바로 되는 일은 없다. --;
여기가 가장 고생한 부분이다. 여기 저기 검색하며 뒤져보다가 최근 버전의 lua에서는 loadlib() 대신 package.loadlib()를 쓰는 것으로 바뀌었다는 내용을 보았다(링크는 잊어버렸다).
어쨌든 package.loadlib()로 바꿔서 시도해봤다.
> package.loadlib('hello_world.so', 'init')()
stdin:1: attempt to call a nil value
stack traceback:
stdin:1: in main chunk
[C]: ?
>
stdin:1: attempt to call a nil value
stack traceback:
stdin:1: in main chunk
[C]: ?
>
또 안된다. --; 대신 에러 메시지는 달라졌다. 여기 저기 뒤져봤지만, 해결책은 찾지 못했다.
거의 포기하려다가 혹시나 하는 마음으로 so 파일의 경로에 './'를 추가해 봤다.
> package.loadlib('./hello_world.so', 'init')()
> greet()
hello world!
>
> greet()
hello world!
>
드디어 성공이다! 이거 하나 띄우려고 며칠을 고생했던가... 젠장, 문서에 몇 글자만 고쳐져 있었으면 이렇게 고생을 안 했을텐데.. 루아에 대해 전혀 모른 상태여서 더 어려운 점도 있었다.
어쨌든 이번 일로 얻은 교훈은 있다.
교훈
* 문서를 참조할 때는 그대로 믿지 말라.
* 오래 방치된 문서는 누군가를 삽질의 세계로 인도할 수 있다.
* 문서를 참조할 때는 그대로 믿지 말라.
* 오래 방치된 문서는 누군가를 삽질의 세계로 인도할 수 있다.
(추가)
이 글을 쓰면서 examples/hello_world/README 파일을 열어 보았더니, 거기에는 다음과 같은 내용이 있는 게 아닌가! 이 파일을 열어 보았다면 한 번의 삽질은 줄일 수 있었을 텐데, 가까운 곳을 찾지는 않고 먼 곳을 뒤지고 있었던 것이다.
ubuntu@ubuntu:~/hello_world$ cat README
this example will build an extension module as a shared library, use
loadlib() from within the lua interpreter to load the library, it will
then export a function named greet() which you can call.
> loadlib('./hello_world.so', 'init')()
> greet()
Hello world!
>
this example will build an extension module as a shared library, use
loadlib() from within the lua interpreter to load the library, it will
then export a function named greet() which you can call.
> loadlib('./hello_world.so', 'init')()
> greet()
Hello world!
>
교훈 추가
* 패키지나 소스를 사용하기 전에 첨부된 README 파일은 꼭 읽어보자.
* 패키지나 소스를 사용하기 전에 첨부된 README 파일은 꼭 읽어보자.