SDK 파일을 받아 C++로 DLL wrapper를 만들던 중, 이전에는 전혀 없던 컴파일 오류들이 발생했다. 같은 SDK를 사용할 때 .exe 파일을 만들던 프로젝트에서는 오류가 전혀 없었고, DLL 프로젝트 빌드할 때만 오류가 발생했다.
초기 코드에서의 #include 순서는 다음과 같았다:
cppCopyEdit#include "SDK1.h"
#include "SDK2.h"
#include <opencv2/opencv.hpp>
이 코드는 EXE 프로젝트에서는 정상적으로 컴파일되었지만,
DLL 프로젝트에서 컴파일하자 다음과 같은 구문오류들이 SDK 헤더에서 발생했다:
bashCopyEdit'(': illegal token on right side of '::'
'std::tr1': warning STL4002: The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED.
syntax error: ')' was unexpected here; expected ';'
syntax error: unexpected token ')' following 'expression-statement'
#include 순서를 바꾸었을 뿐인데, 문제가 완전히 해결되었다.
#include <opencv2/opencv.hpp>
#include "SDK1.h"
#include "SDK2.h"
이렇게 순서를 바꾸자 SDK 헤더파일에서 발생하던 구문오류가 전부 사라졌다.
컴파일러는 헤더를 포함한 순서에 따라 전처리기 매크로 정의, 타입 선언, 템플릿 해석 방식 등이 달라질 수 있다.
OpenCV 같은 대형 라이브러리를 먼저 include하면 내부적으로
#define NOMINMAX<memory> 같은 표준 헤더 선행 포함등이 이루어져 이후에 포함되는 SDK 헤더와 매크로 충돌, 네임스페이스 문제를 예방할 수 있다.EXE 빌드와 DLL 빌드는 프로젝트 속성이나 런타임 환경이 달라질 수 있기 때문에,
헤더 포함 순서에 따라 빌드 결과가 달라질 수 있다.
C++에서는 #include 순서가 실제로 빌드 결과에 영향을 줄 수 있다.
특히 외부 SDK, 대형 라이브러리(OpenCV, Windows API 등), 매크로 사용이 많은 코드베이스에서는 더욱 주의해야 한다.
정리:
#include순서를 무시하지 말자.#define,#pragma,extern "C"등의 전처리기는 포함 순서에 따라 결과가 달라진다.- DLL 환경과 EXE환경은 다르다