gpt4 book ai didi

当实现位于多个库中时,Delphi [weak] 引用属性会生成 "Invalid class typecast"

转载 作者:行者123 更新时间:2023-12-03 14:42:30 24 4
gpt4 key购买 nike

Delphi Berlin 10.1 添加了[弱]引用。 Marco Cantu's Blog有一些基础知识。

为了进行测试,我创建了两个 COM 库,其中包含两种自动化对象类型。容器对象保存内容对象的列表,而内容对象保存对其容器的弱引用。

以下两种场景经过测试并正常工作(弱引用设置为空并释放内存):

  • 具有接口(interface)和 CoClass 的单个 COM 库。
  • 两个 COM 库,一个包含接口(interface),另一个包含 CoClass

但是,当我将组件类放入两个单独的库中时,代码会生成“无效的类类型转换”,删除 [weak] 属性后错误就会消失。请原谅奇怪的示例,其目的只是为了使问题最小化,不应将其视为标准编码实践

这是第一个库 .ridl 文件,它定义了接口(interface)和 CoClass容器:

[
uuid(E1EE3651-A400-49BF-B5C5-006D9943B9C0),
version(1.0)

]
library DelphiIntfComLib
{

importlib("stdole2.tlb");

interface IMyContainer;
interface IMyContent;
coclass MyContainer;


[
uuid(A7EF86F7-40CD-41EE-9DA1-4D9B7B24F06B),
helpstring("Dispatch interface for MyContainer Object"),
dual,
oleautomation
]
interface IMyContainer: IDispatch
{
[id(0x000000C9)]
HRESULT _stdcall Add([in] IMyContent* AMyContent);
};

[
uuid(BFD6D976-8CEF-4264-B95A-B5DA7817F6B3),
helpstring("Dispatch interface for MyContent Object"),
dual,
oleautomation
]
interface IMyContent: IDispatch
{
[id(0x000000C9)]
HRESULT _stdcall SetWeakReferenceToContainer([in] IMyContainer* AContainer);
};

[
uuid(1F56198B-B1BE-4E11-BC78-0E6FF8E55214)
]
coclass MyContainer
{
[default] interface IMyContainer;
};

};

这是我的容器实现

unit Unit1;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, DelphiIntfComLib_TLB, StdVcl, Generics.Collections;

type
TMyContainer = class(TAutoObject, IMyContainer)
private
FList: TList<IMyContent>;
protected
procedure Add(const AMyContent: IMyContent); safecall;
public
Destructor Destroy; override;

procedure Initialize; override;

end;

implementation

uses ComServ;

procedure TMyContainer.Add(const AMyContent: IMyContent);
begin
FList.Add(AMyContent);
AMyContent.SetWeakReferenceToContainer(self);
end;

destructor TMyContainer.Destroy;
begin
FList.Free;
inherited;
end;

procedure TMyContainer.Initialize;
begin
inherited;
FList := TList<IMyContent>.create;
end;

initialization
TAutoObjectFactory.Create(ComServer, TMyContainer, Class_MyContainer,
ciMultiInstance, tmApartment);
end.

我的第二个库引用第一个库,并且仅包含我的内容界面的 CoClass

[
uuid(65659EE4-1949-4112-88CA-F2D5B5D8DA2C),
version(1.0)

]
library DelphiImplComLib
{

importlib("stdole2.tlb");
importlib("DelphiIntfComLib.dll");

coclass MyContent;


[
uuid(79D1669A-8EB6-4AE6-8F4B-91137E6E6DC1)
]
coclass MyContent
{
[default] interface IMyContent;
};

及其弱引用的实现

unit Unit2;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
ComObj, ActiveX, DelphiImplComLib_TLB, StdVcl, DelphiIntfComLib_TLB;

type
TMyContent = class(TAutoObject, IMyContent)
private
[Weak] //If included will cause "invalid class typecast" error
FContainer : IMyContainer;
protected
procedure SetWeakReferenceToContainer(const AContainer: IMyContainer); safecall;
end;

implementation

uses ComServ;

procedure TMyContent.SetWeakReferenceToContainer(const AContainer: IMyContainer);
begin
FContainer := AContainer;
end;

initialization
TAutoObjectFactory.Create(ComServer, TMyContent, Class_MyContent,
ciMultiInstance, tmApartment);
end.

我测试如下

program Project13;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,
DelphiImplComLib_TLB in 'impl\DelphiImplComLib_TLB.pas',
DelphiIntfComLib_TLB in 'Intf\DelphiIntfComLib_TLB.pas';

var
GMyContainer : IMyContainer;
GMyContent : IMyContent;
begin
GMyContainer := CoMyContainer.Create;
GMyContent := CoMyContent.Create;
GMyContainer.Add(GMyContent);
end.

为什么在拆分实现时会出现错误?如何缓解这个问题?

最佳答案

不要对 COM 接口(interface)使用 [Weak]。它不适合与 COM 一起使用。 [弱] 只能用于内部非导出 COM 接口(interface)。

原因是 COM 接口(interface)实现(甚至可能不是由 Delphi 类实现)无法正确处理[弱]引用。此外,您拥有的 COM 库不共享基本 TObject 的相同实现。您可能可以使用共享的rtl包构建所有东西,但即便如此......您还是在地雷上跳舞。

关于当实现位于多个库中时,Delphi [weak] 引用属性会生成 "Invalid class typecast",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39595842/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com