2011. 3. 31. 12:59

.exe의 export 함수를 이용한 개발 방법론 (공통함수 처리, 효율적인 Third-party plug-in 구조)

보통 혼자 혹은 협업으로 개발할 때, .exe 보다는 .dll를 선호하는 경향이 있습니다.
그래서, 보통 제품의 모듈수로 보자면,

.exe 개수 < .dll 개수

와 같더군요.

그런데, .exe나 .dll 모두 같은 PE 구조 이기 때문에, .exe도 .dll 처럼 export가 가능하다는 것을 아실런지요?

다음과 같은 상황을 고려해 봅시다.



즉, a.exe / d1.dll / d2.dll / d3.dll이 있고 4개의 모듈 모두 공통된 s.cpp를 포함하여 빌드가 되었다고 가정합니다.
이런 경우 다음과 같은 고려 사항이 발생합니다.

  • 동일한 s.cpp의 코드 바이너리는 중복적으로 메모리를 차지한다.
  • s.cpp의 코드가 변경되면, 모든 바이너리가 변경된다.

사실 s.cpp를 공통으로 포함하여 빌드하는것 자체가 모순일 수 있습니다. 즉, s.cpp를 따로 s.dll로 하면 되니깐요. 하지만, 의외로 위와 같은 경우도 많이 발생합니다.

이럴때 .exe도 .dll 처럼 아래와 같이 개발한 모델은 다음과 같습니다.

즉, .exe에서만 s.cpp를 빌드하고, 해당 s.cpp 함수를 export 합니다.
그리고, 하부 dll들은 ::GetProcAddress(NULL, "...")로 얻어진 함수를 호출하면 됩니다.
이런 경우,

  • s.cpp의 중복을 막을 수 있다.
  • s.cpp가 변경되어도 a.exe만 변경이 있고, 이외는 변경되지 않는다.

와 같은 장점이 생깁니다. 물론, 하부의 d1.dll ~ d3.dll은 s.cpp가 없기 때문에, stand alone으로 실행되기는 힘들 수 있습니다. 즉, 극단적인 경우 d1.dll ~ d3.dll를 LoadLibrary(...)하는 .exe를 찾아 모두 s.cpp의 함수들을 export해야 합니다.

또한 위와 같은 모델은 Third-part에 제공되는 plug-in 구조에 적합할 수 있습니다. (사실 이것이 중요합니다.)
즉, d1.dll ~ d3.dll은 모두 Third-part에서 구현되는 경우, plug-in에 공통적으로 제공해 줘야 하는 기능이나 함수가 필요한 경우 응용할 수 있습니다. 이런 경우, s.cpp를 각 Third-part에 공유해 주지 않아도 되기 때문에, 보다 보안성을 유지할 수 있습니다. 또한 s.cpp 수정에 따른 모듈 교체 과정이 필요없습니다. 그리고, plug-in 개발자도, 주요한 중요 함수를 GetProcAddress(NULL, ...)을 통해 손쉽게 호출할 수 있는 장점이 생깁니다.

마지막으로, .exe를 .dll 처럼 export하는 방법은 쉽습니다.
.dll 처럼 구현하면 됩니다. 즉, __declspec(dllexport)를 붙이기만 하면 됩니다.
물론, .exe이기 때문에, dllmain은 구현할 필요가 없습니다.