본문 바로가기
프로그래밍/PC

Interface 요약 #2

by 사악신 2012. 4. 19.

지금으로부터 무려 10년전인 2002년 5월경, 델마당 개인게시판에 올렸던 총 9회의 글입니다. 유실된 줄 알았는데 싸이월드 게시판에 있는 걸 확인하고 복구합니다.;;

 

 

4. GUID(Globally Unique Identifier)

  • GetInterface 와 as 연산자를 사용하기 위해선 필요함(따라서 COM외에도 사용됨)
  • Ctrl + Shift + G 로 생성 혹은 CoCreateGuid (Win API) 함수 호출
  • 유일한 값임(현재 시간, 현재 프로세스 번호, MAC Address 등으로 생성)
TGUID = record
  D1: LongWord;
  D2: Word;
  D3: Word;
  D4: array[0..7] of Byte;
end;

 

  • MyGuid:= ['{2DE825C1-EADF-11D2-B39F-0040F67455FE}'];
  • MyGuid: TGUID = (D1: $2DE825C1; D2: $EADF; D3: $11D2; D4: ($B3, $9F, $00, $40, $F6, $74, $55, $FE));

 

5. interface의 실행

  • interface자체는 인스턴스를 생성할 수 없으므로 객체를 통해 구현된다.
type
  TFormattedInteger = class(TObject, IFormattedNumber)
  private
    FValue: integer;
  public
    constructor Create(AValue: integer);
    function FormattedString: string;
    procedure SetValue(AValue: integer);
  end;

constructor TFormattedInteger.Create(AValue: integer);
begin
  inherited Create;

  FValue:= AValue;
end;

function TFormattedInteger.FormattedString: string;
begin
  Result:= 'The value is ' + IntToStr(FValue);
end;

procedure TFormattedInteger.SetValue(AValue: integer);
begin
  FValue:= Value;
end;

 

  • 상기 코드를 컴파일하면 다음과 같은 에러가 발생한다.

Undeclared identifier: 'QueryInterface'

Undeclared identifier: '_AddRef'

Undeclared identifier: '_Release'

(interface는 함수에 대한 선언만 있으므로 상속받은 객체에서 이를 구현해 줘야하기 때문이다. 즉, 상기 함수는 IUnknown 인터페이스에 선언된 함수이다.)

 

IUnknown = interface
  ['{00000000-0000-0000-C000-000000000046}']
  function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  function _AddRef: integer; stdcall;
  function _Release; integer; stdcall;
end;

 

QueryInterface

  • const: var 처럼 reference 값을 넘겨주나 읽기만 할 수 있음. 즉, 수정할 수 없음.
  • out: var 처럼 reference 값을 넘겨주나 자동으로 초기값이 설정된다. 즉, 특별한 입력은 없고 출력만 필요한 경우 사용
  • stdcall: MS사에서 정한 함수이니 당연히... ㅡ..ㅡ
  • 인터페이스의 포인터를 요구하는 함수로 만약 객체에 의해 해당 인터페이스가 실행될 수 있으면(혹은 구현되어 있으면) 0을 함수값으로 반환하고 Obj 파라미터로 해당 인터페이스를 반환하며 실행될 수 없으면(혹은 구현되어 있지않으면) 함수값으로 E_NOINTERFACE를 반환한다.

 

_AddRef

  • 어떤 객체가 인터페이스의 포인터를 획득(인터페이스는 자체적으로 인스턴스를 생성할 수 없기 때문에 항상 객체를 대동한다.)하게되면 이 함수를 호출하여 인터페이스의 참조계수를 증가시킨다.

 

_Release

  • 객체가 인터페이스의 사용이 끝나면 참조계수를 감소시키기 위하여 호출하는 함수이다. 만약, 참조계수가 0이 되면 객체를 소멸시킨다.(nil 대입)
type
  TFormattedInteger = class(TObject, IFormattedNumber)
  private
    FRefCount: integer;
    FValue: integer;
  public
    constructor Create(AValue: integer);

    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: integer; stdcall;
    function _Release: integer; stdcall;

    function FormattedString: string; virtual;
    procedure SetValue(AValue: integer);
  end;

constructor TFormattedInteger.Create(AValue: integer);
begin
  inherited Create;

  FValue:= AValue;
end;

function TFormattedInteger.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
const
  E_NONINTERFACE = $80004002;
begin
  if GetInterface(IID, Obj) then // Win API
    Result:= 0
  else
    Result:= E_NOINTERFACE;
end;

function TFormattedInteger._AddRef: integer; stdcall;
begin
  Dec(FRefCount);
  Result:= FRefCount;
  if FRefCount = 0 then
  Destroy;
end;

function TFormattedInteger.FormattedString: string;
begin
  Result:= 'The value is ' + IntToStr(FValue);
end;

procedure TFormattedInteger.SetValue(AValue: integer);
begin
  FValue:= Value;
end;

 

 

 

 

 

반응형

'프로그래밍 > PC' 카테고리의 다른 글

Interface 요약 #4  (0) 2012.04.19
Interface 요약 #3  (0) 2012.04.19
Interface 요약 #1  (0) 2012.04.19
파스칼로 만든 부트로더... - 1 -  (0) 2012.04.09
GStreamer 빌드하기 - Visual Studio 2008 Express  (0) 2011.12.23

댓글