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;
TInterfacedObject = class(TObject, IUnknown)
protected
FRefCount: Integer;
function QueryInterface
(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
procedure BeforeDestruction; override;
property RefCount: Integer read FRefCount;
end;
procedure TInterfacedObject.BeforeDestruction;
begin
if RefCount <> 0 then Error(reInvalidPtr);
end;
function TInterfacedObject.QueryInterface
(const IID: TGUID; out Obj): HResult;
const
E_NOINTERFACE = $80004002;
begin
if GetInterface(IID, Obj) then
Result := 0 else Result := E_NOINTERFACE;
end;
function TInterfacedObject._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then Destroy;
end;
您可能想知道TInterfaceedObject实现的_Release方法。对于分配给超出范围的类的每个接口,都会自动调用_Release方法。很明显,在DoThis过程的末尾,程序执行将返回它来自哪里,因此,你的局部类和接口声明会落在声明它们的作用域之外。由于我们定义了两个接口,_Release将被调用多少次?答案是亮闪闪的“2”!一旦我们的引用计数为零,那么MyClass就会被 Delphi 自动释放。多么漂亮和干净! source of the answer
3条答案
按热度按时间hec6srdp1#
创建新的ActiveX库。您可以在ActiveX选项卡中找到它。(文件-新建-其他- ActiveX - ActiveX库)
jv2fixgn2#
这里你有如何做到这一点:
Delphi 中的COM编程介绍那么,什么是接口呢?接口是COM技术的核心。当我使用界面这个词时,不要把它与用户交互的视觉显示混淆。它实际上是一个相当新的保留字并入 Delphi 。接口只不过是用来操作对象的一组抽象方法。
我们在上一课中确定了接口不是类;它是一个接口。因此,我们必须这样宣布。让我们来探讨一些界面特征。
现在我们已经了解了接口可以做什么和不能做什么,让我们来看看声明接口是什么样子的。
在GUID上,我相信你想知道那一大串疯狂的字符是什么。它被称为GUID,代表全局唯一标识符。有些人把它读为“gwid”或“Gooey ID”。下面是GUID的一些特征:
好的,但是我如何实现一个接口呢?这是个好问题。答案是:不能直接实现接口。您必须创建一个将实现您的接口的类。请参考下面的编码示例。
上面列出的代码示例非常简单,同时仍然具有某种类型的视觉功能。让我们仔细看看过程TextBtnClick。是不是少了什么?如果你有?我没有注意到,我们没有显式地释放接口。这看起来是内存泄漏,但表象是骗人的。一旦接口超出范围, Delphi 实际上会自动为您释放接口!当过程或函数结束时,在过程或函数中声明的接口自然会超出范围。当对象被释放或程序结束时,在类中声明或全局声明的接口自然会超出范围。
现在我们需要讨论引用计数。每次检索对象的接口时,例如MyClass:= MyClass; Delphi 将使用IUnknown的_AddRef函数自动增加其引用计数。当接口福尔斯作用域时, Delphi 会自动调用IUnknown的._Release函数。如果你还没有弄明白,IUnkown也是一个接口,既然我们已经知道接口不能实现它定义的方法,那么你可能想知道AddRef和Release是从哪里来的。答案是TInterfacedObject!什么是TInterfacedObject?TInterfacedObject和IUnknown在system.pas中定义。在我详细说明这一点之前,我们至少需要看看代码:
TInterfacedObject的IUnkown声明及其实现
代码可能看起来有点吓人,但我们将逐步完成,因为理解引用计数对于有效地在COM中编程至关重要。从上面的代码中可以明显看出,TInterfacedObject实现了IUnkown中定义的方法。当你创建一个使用TInterfacedObject的类时,你实际上是在告诉这个类,如果一个接口被分配给它,它将被引用计数。
让我们看一段简单的代码,这样我就可以描述发生的过程。
当您使用直接赋值将MyInterface赋值给MyClass时, Delphi 会自动调用_AddRef方法。这对MyClass说,“嘿,一个接口正在引用你!我们将增加您的引用计数。”如果您要将上述代码更改为以下内容:
请注意,我添加了一个名为MyInterface 2的新变量。既然我们现在设置两个不同的接口等于MyClass,猜猜MyClass会发生什么?的引用计数?它变成了2,因为我们现在有两个接口分配给它!
您可能想知道TInterfaceedObject实现的_Release方法。对于分配给超出范围的类的每个接口,都会自动调用_Release方法。很明显,在DoThis过程的末尾,程序执行将返回它来自哪里,因此,你的局部类和接口声明会落在声明它们的作用域之外。由于我们定义了两个接口,_Release将被调用多少次?答案是亮闪闪的“2”!一旦我们的引用计数为零,那么MyClass就会被 Delphi 自动释放。多么漂亮和干净!
source of the answer
mftmpeh83#
通过this site,这是在 Delphi 中开发COM的良好起点。它有关于 Delphi 中COM技术的教程、文章和代码。可能对你有帮助