[C++Builder] Graphics32 설치

Delphi, C++Builder 에서 사용하는 Third Party Component 중에서 유명한 Graphics32 가 있다. 이미지의 회전, 변형, 레이어, 색상 변환 등. 어지간한 그래픽 기능은 Graphics32 를 사용하면 된다. 그러나 C++Builder 에서는 설치시에 문제가 발생한다. 좀 어처구니 없는 실수 때문인데 function 하나를 중복시켜 버린 것이다. Installation 시에 다음과 같은 Error 가 발생한다.

[Pascal Error] GR32_Dsgn_Misc.pas(128): Identifier redeclared: 'TCustomClassProperty.GetClassList'



이걸 해결하려면 GR32_Dsgn_Misc.pas 에서 다음을 찾아서 지워야 한다.
(If you want to compile it, following function should be deleted in GR32_Dsgn_Misc.pas.)

{$IFDEF BCB}
class function TCustomClassProperty.GetClassList: TClassList;
begin  
  Result := nil;
end;

...

{$ENDIF}



위의 함수를 지워야 한다. 왜일까? 해당 함수가 이미 먼저 구현(Implementation)되어 있기 때문이다.
83번 line 을 보면 다음과 같이 이미 구현되어 있다.

class function TCustomClassProperty.GetClassList: TClassList;
begin  
  Result := nil;
end;



결국, 같은 함수를 중복시킨 셈인데 좀 어처구니 없는 실수이긴 하지만, 여기에서 Delphi 와 C++ 간의 추상클래스(abstract class) 를 다루는 방법이 다르다는 것을 알 수 있다. 추상클래스라는 것은 해당 클래스에서는 껍데기만 만들고 상속받은 클래스에서 구현을 하는 것을 말한다. Delphi 는 procedure, funtion 에 abstract 키워드가 있으면 implementation 에서 함수의 본체를 만들지 않느다. 하지만, C++ 은 해당 함수가 아무런 기능을 하지 않더라도 일단은 구현부가 있어야 한다. 그러므로 C++Builder 를 위해서 아무 내용이 없는 껍데기를 implementation 부에 만들어 주어야 한다. 그것이 다음과 같은 것이다.

{$IFDEF BCB}
procedure TCustomClassProperty.SetClassName(const CustomClass: string);
begin
end;

function TCustomClassProperty.GetObject: TObject;
begin  
  Result := nil;
end;
{$ENDIF}



compiler directive 인 {$IFDEF BCB} 는 C++Builder 이면 다음 내용을 컴파일 하라는 뜻이다. 소스에서 보이듯 아무 내용이 없는 껍데기 뿐이다. interface 부를 보면 다음과 같이 되어 있다.

TCustomClassProperty = class(TClassProperty)  
private    
  function HasSubProperties: Boolean;  
protected    
  class function GetClassList: TClassList; virtual;    
  procedure SetClassName(const CustomClass: string); virtual; {$IFNDEF BCB} abstract; {$ENDIF}              function GetObject: TObject; virtual; {$IFNDEF BCB} abstract; {$ENDIF}  
public    
  function GetAttributes: TPropertyAttributes; override;    
  procedure GetValues(Proc: TGetStrProc); override;    
  procedure SetValue(const Value: string); override;    
  function GetValue: string; override;  
end;


procedure SetClassName 에 {$IFNDEF BCB} abstract; {$ENDIF} 가 있는 것을 알 수 있다. 이것은 C++Builder 가 아니면, 즉, Delphi 이면 abstract 를 포함하라는 뜻이다. Delphi 에서는 abstract 키워드가 있으면 implementation 에서 구현부를 만들지 않는다. C++ 에서는 형식적으로라도 있어야 하므로 abstract 키워드를 제외하고 implementation 부에 구현부를 만들어 주어야 한다. 문제가 된 GetClassList 는 abstract 키워드가 없으므로 implementation 부에 구현부가 있어야 한다. 실제로 83번 line 에 구현부가 있다. 따라서 compiler directive 인 {$IFDEF BCB} ... {$ENDIF} 사이에 GetClassList 의 구현부가 또 있으면 C++Builder 의 입장에서는 중복되게 되는 것이다. 이건 아무리 봐도 실수이지만, Delphi 에서는 문제없이 compile 되므로 제작자들이 알기 어렵다. 버그 리포팅도 해보고 NewsGroup 에도 올려 봤지만 그다지 관심이 없는것 같다. 중요한 문제라고 생각하지 않는것 같다.