|
제가 지난 번에 올린 질문에 대한 임프님의 답변내용입니다.
//------------------------------------------------------
임펠리테리입니다.
볼랜드의 FAQ에는 그 에러에 대한 답변이 두개가 있습니다. 말씀하신 것은 첫번째구요, 그보다 전에 답변된 것을 보시면 정확한 해답이 있습니다.
정확히 말해서, 에러의 원인은 이름 충돌(name conflict)입니다. TClientSocket에 보시면 Port라는 프로퍼티를 정의하기 위해 읽을 때는 GetPort(), 쓸 때는 SetPort() 함수를 호출합니다. (프로퍼티 이름에 Get~, Set~ 을 붙여 메소드 이름을 짓는 것은 VCL의 관행입니다.)
그런데 Win32 API 함수에 SetPort() 라는 이름의 함수가 있으며, 실제로는 안시형의 스트링과 유니코드 스트링 각각에 대해 함수가 있어서 SetPortA(), SetPortW()로 디파인되어 있습니다. 그래서 결국 링커에서 SetPortA() 라는 API 함수와 충돌을 한겁니다.
API 함수인 SetPort()가 선언된 곳은 winspool.h 이며, 이것은 다시 windows.h에 인클루드되어 있습니다. 그리고 vcl.h에서 다시 windows.h를 인클루드하고 있습니다. 결국, vcl.h가 ScktComp.hpp보다 앞에 있게 되면 문제가 발생합니다. 그런데, 실제로, 새로운 폼을 만들면 vcl.h는 자동으로 언제나 cpp파일의 가장 앞에 인클루드되고, 폼에 클라이언트 소켓을 놓은 순간 ScktComp.hpp가 인클루드됩니다. 그러므로 언제나 API 함수의 선언이 앞에 있게 되지요.
그래서, 아래 조재영님이 말씀하신 것처럼 헤더파일의 인클루드 순서를 바꾸는 것이 해결책이 될 수 있습니다. 하지만, 이렇게 해서는 좀 복잡해지거나 다른 문제를 발생시키게 될 수도 있습니다.
이런 경우에 표준적인 해결책은, 헤더파일을 작성하는 묵시적인 룰 중 한가지를 이용하는 것입니다. 유심히 보셨다면, 빌더에서 사용하는 모든 *.h, *.hpp 들과 API 함수를 위해 마이크로소프트로부터 받아온 windows.h 등 모든 win32 헤더파일들의 가장 앞에 다음과 같은 프리프로세서가 있다는 것을 아실겁니다.
#ifndef _WINDOWS_
#define _WINDOWS_
(...실제 헤더내용...)
#endif /* _WINDOWS_ */
이런 프리프로세서는 두가지 역할이 있습니다. 첫번째는, 한번 인클루드된 헤더가 또다시 인클루드되지 않도록 방지합니다. 두번째 역할은, 미리 _WINDOWS_ 라는 선언을 해버림으로써 이 헤더파일이 인클루드되는 것을 강제로 막을 수 있다는 겁니다. 이것이 바로 우리가 찾던 바로 "그거!"지요.
결과적으로... 해결책은 아시겠지요? cpp파일 맨 위에 있는 #include <vcl.h> 바로 앞에서 #define _WINSPOOL_ 라고 한줄을 추가해버리면 됩니다.
참고로, 델파이에서 이런 문제는 발생하지 않는 이유는, 델파이에서 인클루드에 해당하는 uses는 C/C++의 #include와는 달리, 순환적으로 계속 인클루드하지 않기 때문입니다.
그럼 참고하시길...
//----------------------------------요기까지.
안녕하세요.
지난 번 문제는 시간에 쫓겨서 결국은 손에 익은mfc로 코딩해서 급한 불은 껐습니다.
그리고 나니 다시 빌더로 구현 해내고 싶은 생각이 불끈 솟아올라
들어와보니 임프님이 답변을 주셨더군요. 감사합니다.
그런데
::결과적으로... 해결책은 아시겠지요? cpp파일 맨 위에 있는 #include <vcl.h> 바로
::앞에서 #define _WINSPOOL_ 라고 한줄을 추가해버리면 됩니다.
대로 하니 winspool.h에 가서
, expected.라는 에러가 주루룩 뜨고는 컴파일 에러가 납니다.
그래서 질문인데요.. cpp파일에 추가 하는 것이 맞습니까?
혹시 <sctcomp.h>파일이 인클루드 되어있는 헤더 파일에 하는 것은 아닌가요?
제가 c++개념에 좀 약해서리요...(T_T)
여전히 빌더가 멀게 느껴지는 ant소년
|