Archive for August, 2009
Nokia Qt SDK
[옛날 블로그 글입니다. 2009.08.29]
얼마전에 트위터에 올린 그 내용입니다. 여러 OS에서 Qt 개발을 편하게 할 수 있는 IDE를 만들어서 배포하고 있네요. 아래 노키아 사이트에서 다운로드 할 수 있습니다.
http://qt.nokia.com/downloads
유명한 C++ 라이브러리는 에러 처리를 어떻게 하나 궁금해서 Qt를 좀 봤는데요, 노키아에서 이렇게 훌륭하게 정리해 놓은 것을 보고 좀 충격을 받았습니다.
윈도우 플랫폼 용을 받아 봤더니 MinGW와 Qt 그리고 통합 개발 환경까지 설치가 되네요. 비주얼스튜디오나 XCode처럼 한 프로그램에서 코딩하고, WYSIWYG으로 UI를 만들고, 디버깅도 하고, 도움말도 볼 수 있습니다. C++ 코드 편집중에 문법이 틀린 문장은 빨간 줄도 쳐줄만큼 감동적입니다. ^^
굳이 Qt를 안쓰더라도 윈도우에서 GCC로 개발을 할 때 정말 유용할 것 같네요. C++을 처음 배우는 사람들에게도 어쩌면 비주얼스튜디오 익스프레스 버전보다 더 나은 선택이 될 수도 있겠네요. 여러 OS에서 사용하는 GCC와 Qt에 먼저 익숙해진다는 관점에서는요.
C++ 라이브러리 만들기는 어려워
[옛날 블로그 글입니다. 2009.08.24]
[추가1. VC++의 예외 바이너리 호환성에 대해 내용 추가(정정)했습니다]
오랜만에 시간이 좀 나서, 요새 머리를 괴롭히는 이슈를 좀 적어 봅니다.
회사에서 C++ 라이브러리를 만들고 있습니다. 이녀석을 바이너리(dll)로 배포할 목적입니다. 컴파일러 버전별로 다 제공하기에는 무리가 있으니, 컴파일러 버전에 독립적인 바이너리가 되도록 하고 싶습니다.
이 목적을 달성하기 위해서는
- DLL에서 할당한 메모리를 EXE에서 해제하면 안됩니다.
- DLL의 인터페이스에서 STL을 쓰면 안됩니다.
- DLL에서 예외를 던지면 안됩니다.
이 규칙을 모두 만족하는 인터페이스란
- 바로 Windows API와 같은 C 함수들
- COM 인터페이스
정도가 되겠네요.
DLL에서 할당한 메모리는 DLL에서 해제
메모리를 할당해 준 CRT가 해제해야 한다는 얘기죠. 컴파일러 버전에 독립적이려면 DLL을 정적 CRT 라이브러리와 링크하는게 좋은데, 이러면 DLL과 EXE가 사용하는 CRT가 달라집니다. 그래서 DLL에서 할당한 메모리를 EXE에서 해제하면 안됩니다.
같은 컴파일러 버전으로 빌드된 DLL과 EXE이더라도 CRT가 다르면 조심해야 합니다. 같은 CRT(DLL)를 쓴다면 신경 안 써도 되구요.
그래서 DLL에서 문자열이나 메모리 블럭을 건네줄 일이 있다면, COM처럼 자기네 CRT에서 할당/해제하는 SysAlloc(), SysFree() 같은 함수를 만들어 제공하기도 합니다. DLL에서 SysAlloc()으로 메모리 블럭을 할당해서 주면 EXE에서 SysFree()로 해제하는 식이죠.
아니면 전통적인 방식으로 EXE에서 DLL에게 '메모리 블럭 크기가 몇이냐?' 물어보고 나서, EXE가 메모리를 할당해서 DLL에게 '여기에 넣어줘'라고 말하는 방법이 있습니다.
SysAlloc() 방식은 크기를 물어보는 등의 귀찮은 작업이 없는게 장점이고, 전통적인 방식은 사용자(EXE)가 자신의 메모리 풀 같은 것은 만들어 쓸 때 유리한 면이 있습니다.
DLL의 인터페이스에서 STL을 쓰면 안됨
STL의 구현이 컴파일러 버전별로 달라서 바이너리 호환성이 없는 것도 문제고, 메모리가 DLL경계를 넘어서는 경우도 있어서 안된다고 하네요.
네, 그래서 다른 언어 부럽지 않게 std::string을 반환하고 싶은 바램은 포기해야 합니다.
DLL에서 예외를 던지면 안됨
역시나 C++에 바이너리 표준이 없기 때문인데요, 예외 매커니즘을 구현하는 방식도 표준화 되어 있지 않기 때문에 컴파일러별로 다른게 현실입니다. 그래도 Visual C++이라면 같지 않을까 하는 기대감에 테스트를 해봤는데요.
VC++ 2008에서 예외를 던지는 DLL을 만듭니다. 그리고 VC++ 6.0, 2003, 2005, 2008, 2010에서 예외를 받는 EXE를 만듭니다. 결과는.. VC++ 6.0, 2003에서는 프로그램이 죽습니다. -_-;;
[추가1. 위에 테스트는 std::exception 오브젝트를 던지는 것였는데, std::exception의 구현차이 때문에 예외를 못받은 것 같습니다. 그냥 직접 만든 클래스의 포인터를 넘기니 모든 버전의 VC++에서 예외를 잘 받네요. 고민입니다. gcc도 비슷하다면 예외를 써도 되지않을까 고민중입니다.. ]
이로서 다른 언어 부럽지 않게 예외 처리를 하고 싶은 바램도 포기해야 합니다.
마무리
요즘의 언어처럼 쓰기 편한 인터페이스를 만들고 싶었는데 C++은 C++스럽게 써야만 하는 부분이 있었네요. 이래서 MS에서 닷넷 프레임웍을 만들었나 싶은 생각도 들었습니다.
참고자료
Binary-compatible C++ Interfaces, Chad Austin, 2002.02.15http://chadaustin.me/cppinterface.html
