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
[75883] Re:델파이 컴파일러에서 닭짓을 해놨기 때문
빌더(TWx) [builder] 1715 읽음    2020-06-11 11:58
초심 님이 쓰신 글 :
: 기존 작업해놓았던 모든 Direct2D 프로젝트 파일들이
: 시드니 10.4에서 클래식 컴파일러로 컴파일하면 전부 에러가 납니다.
:
: //---------------------------------------------------------------------------
:
: #include <.h>
: #include <direct2d.hpp>
: #pragma hdrstop
:
: #include "Unit3.h"
: //---------------------------------------------------------------------------
: #pragma package(smart_init)
: #pragma resource "*.dfm"
: TForm3 *Form3;
: //---------------------------------------------------------------------------
: __fastcall TForm3::TForm3(TComponent* Owner)
:  : TForm(Owner)
: {
: }
: //---------------------------------------------------------------------------
:
:
: <direct2d.hpp> 하나만 인클루드 해도 컴파일 에러가 나버리는데
: 해결할 수 있는 방법이 없을까요.
:
:



답변:


1.

델파이 파스칼 언어는 anonymous namespace, inline namespace 등
언어가 갖고있어야 할 기본적인 namespace 개념을 갖고있지 않아요.

다음과 같이 Unit1.pas 란 파일이 있을 때

'Unit1'이란 파일명이 namespace 처럼 사용될 뿐이고
unit 키워드로 명시되는 유닛 네임은 파일명과 일치해야 합니다.

<Unit1.pas>
unit Unit1;
interface
implementation
end.




2.

Vcl.Direct2D.pas 에 정의되어 있는 EDirect2DException를 예로 들어 봅시다.


파일명이 Vcl.Direct2D.pas 이기 때문에 'Vcl.Direct2D'가 namespace 처럼 사용될 뿐이고
EDirect2DException의 qualified name은 'Vcl.Direct2D.EDirect2DException'가 되죠.

Unit1 에서 EDirect2DException를 참조할 경우...

unit Unit1;

interface

implementation

uses Vcl.Direct2D;

procedure foo;
var f: Vcl.Direct2D.EDirect2DException;
begin

end;
end.


위와 같이 qualified name 'Vcl.Direct2D.EDirect2DException'으로 참조할 수 있습니다.




3.

다음 코드를 봅시다.

unit Unit1;

interface

implementation

uses Direct2D;

end.


uses 에 'Vcl.Direct2D'가 아닌 'Direct2D'로 되어 있지만
Direct2D를 오픈하면 Vcl.Direct2D.pas가 열립니다.

여기서 Direct2D는 물리적인 실제 파일인 Vcl.Direct2D.pas 로 매핑되고
실제 유닛파일은 Direct2D가 아닌, Vcl.Direct2D.pas 파일이 사용 됍니다.

유닛 Alias 역할을 하게 되는 거죠.




4.

따라서 다음 코드는 컴파일이 돼야 할 것 같지만 컴파일이 안 됍니다.

unit Unit1;

interface

implementation

uses Direct2D;

procedure foo;
var f: Vcl.Direct2D.EDirect2DException;
begin

end;
end.



qualified name을 사용해서 컴파일 돼도록 하려면... Vcl.Direct2D.EDirect2DException을
다음과 같이 Direct2D.EDirect2DException으로 해야 합니다.

uses에 Vcl.Direct2D가 아닌 Direct2D 라는 유닛 Alias를 사용했기 때문에
실제의 원래 파일과는 다른 Direct2D라는 qualified name으로 종속 돼 버리기 때문 입니다.




4.


그런데 uses Direct2D로 지정했는데도
소스코드에 uses Vcl.Consts; 이 포함되면

다음과 같이
'Vcl.Direct2D.EDirect2DException' qualified name 을 사용할 수 있게 됍니다.

unit Unit1;

interface

uses Vcl.Consts;

implementation

uses Direct2D;

procedure foo;
var f: Vcl.Direct2D.EDirect2DException;
begin

end;
end.





5.

또 qulified name을 'Vcl.EDirect2DException'으로 .Direct2D. 없이 사용할 수도 있는데요

unit Unit1;

interface

uses Vcl.Consts;

implementation

uses Direct2D;

procedure foo;
var f: Vcl.EDirect2DException;
begin

end;
end.


qulified name alias가 되는 거죠.


만약 델파이 파스칼 언어가 C++처럼 ISO 국제위원회에서 엄격한 심사를 거쳐 만들어졌다면
위와 같은 식으로 작위적으로 언어를 만들었다간 당장에 퇴짜를 맞았을 겁니다.

이미 사양돼 버린 파스칼 언어를 엄격한 검증 없이, 자기들 독단적으로 정의해서 속된 말로 꼴리는대로
만들어서 사용해도 상관 없으니 저런 식으로 하는 거겠죠.



모든 시스템 API는 C 헤더 파일로 정의 되어있고
파스칼 언어는 헤더 파일을 사용할 수 없으므로 파스칼 유닛으로 인터페이스를 정의해서 사용하는 거고

C++빌더 쪽에선 파스칼 컴파일러가 translation해서 생성한 .hpp 헤더를 사용하게 됍니다.
Vcl.Direct2D.hpp는 Vcl.Direct2D.pas 를 변환해서 델파이 컴파일러가 생성한 산물 입니다.


그리고 위와 같이 Direct2D가 Vcl.Direct2D.pas에 대한 유닛 alias가 되도록
델파이 컴파일러에서 닭짓을 해놨기 때문에

C++ 빌더 쪽에서는 <Direct2D.hpp>와 <Vcl.Direct2D.hpp> 두개의 별개의 헤더파일이 같이 있어야 하고

qulified name을 Vcl.Direct2D.EDirect2DException'으로도 Vcl.EDirect2DException' 으로도 사용하게
델파이 컴파일러를 작위적으로 만들어서 닭짓을 해놨기 때문에

C++에선 namespace conflict가 일어나게 됍니다.

namespace Vcl; 과 namespace Vcl::Direct2D;는 엄연히 서로 다른 qulified name이 돼야 하는 건데
델파이 컴파일러에서 이런 닭짓을 해놨으니.



이 문제를 해결하기 위해선...


1.

델파이 컴파일러가 생성한 헤더파일들을 다 뜯어 고치거나


2.

클래식 컴파일러를 만들 때 namespace conflict가 일어나는 것을 막기 위해
파서에서 namespace를 구분하기 위한 심볼을 파싱 심볼테이블에 정의하도록 하던가.


3.

지금과 같이 엠바에서 클래식(legacy) 컴파일러에 손을 댈 여력이 없어서 작업해 놓지 않았다면...

다음과 같이

소스파일 선두에 NO_USING_NAMESPACE_WINAPI_D3DCOMMON 를 정의해서 사용하면 됍니다.

//---------------------------------------------------------------------------
#define NO_USING_NAMESPACE_WINAPI_D3DCOMMON
#include 
#include 
#pragma hdrstop

#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
	: TForm(Owner)
{
	Vcl::Direct2d::EDirect2DException* v;
}
//---------------------------------------------------------------------------


#include <Vcl.Direct2D.hpp> 대신에
#include <Direct2D.hpp> 로 하는 것은 델파이 컴파일러 닭짓의 산물이므로 안좋은 것임.




+ -

관련 글 리스트
75882 시드니 10.4 Direct2D 컴파일 에러 초심 1287 2020/06/10
75883     Re:델파이 컴파일러에서 닭짓을 해놨기 때문 빌더(TWx) 1715 2020/06/11
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.