C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[5298] Re:소켓에 관한 질문입니다.(절망적) -> 이름충돌입니다
박지훈.임프 [cbuilder] 3135 읽음    2001-02-08 15:21
ant 님이 쓰신 글 :
: 뒤지다 보니 이미 제가 지난번에 한 질문은
: 볼랜드에도 리포트 된 적이 있더군요.
:
: Unresolved external 'Scktcomp::TAbstractSocket::SetPortA(int) - by Borland Developer Support Staff
:
:  Question and Answer Database
:
: FAQ4474C.txt - Unresolved external 'Scktcomp::TAbstractSocket::SetPortA(int)
:
: Category   :Linker
: Platform   :All-32Bit
: Product    :All-CBuilder,  
:
: Question:
: I get this error from BCB3 at link time. How can I fix thism it is from
: one of your libraries!
:
: Answer:
: This was a bug in C++Builder 3 that is fixed by correctly applying the patch.
:
: Goto our website to get the pach:
:
: http://www.borland.com/devsupport/bcppbuilder/patches.html
:
: You need to download the readme separately, please do so and read it carefully
: before installing the patch.
:
: 3/22/99 2:04:28 PM

:
: ...
: 그런데 저는 빌더 4 엔터프라이즈 버전을 쓰고 있고
: FAQ 대로 빌더 4용 패치를 깔았는데도 같은 링크 에러가
: 계속 나는군요...
: 헤더 파일의 인클루드 순서도 이리저리 바꾸어 보았는데...
: 어째 빌더가 저를 반기지 않는 듯 하군여.
: 쩝.
: 혹시 이 모든 것을 알고 있는 분은 없는가요?



임펠리테리입니다.

볼랜드의 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와는 달리, 순환적으로 계속 인클루드하지 않기 때문입니다.

그럼 참고하시길...

+ -

관련 글 리스트
5294 소켓에 관한 질문입니다.(절망적) ant 2850 2001/02/08
5298     Re:소켓에 관한 질문입니다.(절망적) -> 이름충돌입니다 박지훈.임프 3135 2001/02/08
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.