[펌]VC에서 lib 또는 Dll mingw용 으로 변환

개인적으로 Minigw를 이용하여 프로그램을 만들어야 하는 경우가 있는데
정적 DLL이 필요하여 찾아보다가 발견한 문서

출처 : http://www.redwiki.net/wiki/wiki.php/VC%BF%EB%20lib%C8%AD%C0%CF%C0%BB%20mingw%BF%EB%20%B6%F3%C0%CC%BA%EA%B7%AF%B8%AE%B7%CE%20%BA%AF%C8%AF%C7%CF%B1%E2

1 개요
2 그래도 msys가 필요하다!
3 _cdecl일까? _stdcall일까?
4 _cdecl 방식 변환 방법
5 _stdcall 방식 변환 방법
6 한계점
7 마무리
1 개요 #
SDL이나 대규모 라이브러리같은 경우 간단히 쓰고는 싶은데 매번 빌드하려면 고생일 수 밖에 없습니다. 게다가 SDL처럼 LGPL같은게 걸려있으면 DLL 배포가 기본일 경우가 있죠. (이것은 정적 링크를 하기가 버거롭다는 얘기…) 이럴때 괜히 msys에서 빌드하면서 시간죽이는 거보다 간단히 .lib -> .a 로 변환하면 쉽게 해결되는 경우가 많습니다. (오호~  ) 그래도 위 mingw faq의 내용그대로 하면 삽질이 다소 필요해 제나름대로 정리해보았습니다.



2 그래도 msys가 필요하다! #
흐음… 우선 변환작업을 위해서는 다음과 같은 3가지 툴이 필요합니다.
pexports
reimp
dlltool
sed



이중 sed는 정규표현식을 사용하여 text내의 몇몇 문자열내용 수정을 배치처리하는 툴인데, 이것은 cygwin, msys 모두 있으므로 설치할 필요가 없습니다. dlltool 역시 DLL을 조립하거나 그 안에서 symbol 데이타를 묶거나 추출하는 툴입니다. 이것도 gnu 툴이므로 양쪽 개발환경 모두 존재합니다.



pexports는 DLL의 심볼들을 표준출력으로 주욱 나열해주는 프로그램입니다. 이것은 http://www.mingw.org의 다운로드에 가보시면 mingw utilities라고 하는 게 있습니다. 다운받아서 mingw 디렉토리에 설치합니다. mingw 표준 디렉토리에 맞게 압축되어있으므로 cygwin에 푸는 것은 좋지 않은 방법이라고 생각합니다. 다 풀었으면 이제 pexports와 reimp를 사용할 수 있습니다!



3 _cdecl일까? _stdcall일까? #
위 참고 링크와 기타 글을 읽어보면 win32 DLL의 함수호출방식은 _cdecl과 _stdcall 두방식 중 하나를 택하고 있습니다. 그럼 현재 변환하고자 하는 DLL이 둘중 어느방식인지를 알아봐야겠죠. _cdecl로 컴파일되어있는 SDL을 예를 들어보겠습니다. 다음과 같이 실행해보면,
pexports sdl.DLL
함수들 이름이 주욱 나오는데 모두 앞에 _문자가 안붙고 정상적으로 나오는 것을 볼 수 있습니다. 이런 경우가 대부분인데 이때는 _cdecl이므로 가장 쉽게 변환할 수 있는 경우라고 생각하시면 됩니다. 하지만, 몇몇 오픈 소스 라이브러리나 특히 C++로 작성된 라이브러리들은 간혹 _stdcall을 사용할 때가 있는데 위 명령을 실행해보면 함수 이름 앞에 _문자가 붙어나오는 경우입니다. 이럴때에는 _stdcall이라 생각하시면 됩니다.



4 _cdecl 방식 변환 방법 #
이때에도 두가지 방법이 있습니다. .lib가 존재할 경우와 DLL화일만 가지고 있는 경우입니다. .lib가 붙어있는 “완벽한” SDK의 경우라면 다음과 같이 실행하면 됩니다.
reimp sdl.lib
위와 같이 실행하면 libsdl.a라는 화일이 생깁니다. lib 접두어와 .a 확장자는 자동으로 붙으므로 나름대로 이름을 바꿔주면 됩니다. 이제 맘대로 링크해서 쓰면 됩니다. 



헌데, DLL만 배포하는 경우도 많습니다. (오래된 프로젝트일경우가 대부분이죠.  ) 이럴 경우 다음과 같은 방법을 취합니다. 만일 존재하는 DLL이 foo.dll이라고 가정하고 결과 라이브러리 화일을 libfoo.a로 뽑아낸다고 가정하겠습니다.
pexports foo.dll | sed “s/^_//” > foo.def
dlltool -d foo.def -l libfoo.a



이제 링크해서 사용해봅니다.  정말 간단하다는 것을 알수 있습니다. (mingw 개발팀에 찬사를~)



5 _stdcall 방식 변환 방법 #
이 경우는 DLL로부터 밖에 추출할 수 밖에 없습니다. stdfoo.dll을 예로 들어보겠습니다.
pexports stdfoo.dll | sed “s/^_//” > stdfoo.def
dlltool -U -d stdfoo.def -l libstdfoo.a
엇, -U 밖에는 차이가 없죠? 그렇습니다. 위 명령을 요약하면 우선 DLL로부터 심볼을 _문자를 모두 걷어내고 뽑아낸다음, _문자를 앞에 붙여주면서 만들어준다는 뜻입니다. 끝났습니다. 링크해봅니다. 



6 한계점 #
혹시라도 제가 사용법을 잘 몰라서 그럴 수도 있음을 먼저 밝힙니다. 간혹 위 두 방법으로 해봐도 링크가 죽어라 안되는 프로젝트가 간혹있습니다. 다음과 같은 경우입니다.
C++ 빌더와 같은 _fastcall방식의 호출규약을 가진 DLL이나 .lib
DLL상에 static 속성의 전역 변수를 관리하는 라이브러리 (이 경우 되는 경우와 안되는 경우가 있는데 정확히 원인은 모르겠습니다)



7 마무리 #
음하하~ 이제 sourceforge상의 거의 대부분의 win32 라이브러리를 끌어쓸 수 있게 되었습니다. gcc를 애용하시는 분들은 시간나실때마다 받아서 붙여 써보는 것도 좋겠네요.  틀린 부분이 있으면 모래상자에 적어주시면 수정하겠습니다.

댓글 남기기