초심 님이 쓰신 글 :
: 기존 작업해놓았던 모든 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> 로 하는 것은 델파이 컴파일러 닭짓의 산물이므로 안좋은 것임.