지금으로부터 무려 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 |
댓글