【问题标题】:use dispInterface in Delphi with no classid在没有classid的Delphi中使用dispInterface
【发布时间】:2014-02-12 23:57:29
【问题描述】:

我已经将一个类型库导入到具有许多调度接口的 Delphi XE2 中。他们中的大多数都有一个自动创建的 coclass 和相应的 delphi T 接口。

但是,我需要使用的一些调度接口没有 classid;我已经尝试了可以​​在网上找到的每个示例来使用相关的调度接口。界面如下:

DIID_ITableListener: TGUID = '{83D42EA5-2C18-46EB-823B-262D62DF8CF1}';
... 
ITableListener = dispinterface;
...
// *********************************************************************//
// DispIntf:  ITableListener
// Flags:     (4096) Dispatchable
// GUID:      {83D42EA5-2C18-46EB-823B-262D62DF8CF1}
// *********************************************************************//
ITableListener = dispinterface
  ['{83D42EA5-2C18-46EB-823B-262D62DF8CF1}']
  procedure Added(const rowID: WideString; const rowDataObj: IRow); dispid 1610743809;
  procedure Changed(const rowID: WideString; const rowDataObj: IRow); dispid 1610743810;
  procedure Deleted(const rowID: WideString; const rowDataObj: IRow); dispid 1610743811;
  procedure StatusChanged(status: TableStatus); dispid 1610743812;
end;

下面是类型库包装器中另一个接口的示例,它使用了这个分派接口:

procedure subscribeUpdate(updateType: TableUpdateType; const listenerObj: ITableListener);

这是一个提供的 VB.NET 示例,它解释了应该如何使用调度接口:

' If you want to use methods of the ITableListener interface, you must create a 
' class that+ implements the interface. For example,

public class TableListener implements ITableListener { }

' In your application you must create an instance of the class that implements  
' the interface. For example,

TableListener tableListener = new TableListener();

没有 ClassID 我如何在 Delphi 中实现它?如何进行实例化?我认为这与实现 IDispatch 接口后代有关,但再次没有 ClassID,我无法找到使其工作的方法。

救命!

谢谢。

【问题讨论】:

  • 你应该实现这个接口,所以你可以使用任何你喜欢的ClassID。
  • 为了详细说明 Eric 的评论,ITableListener 是一个事件接收器接口,从它被声明为DIID 的事实可以看出。您应该在自己的代码中编写一个实现该接口的类(您不需要 ClassID),​​然后实例化该类并通过其subscribeUpdate() 方法将其传递给另一个 COM 对象。这允许 COM 对象在需要时使用您的 ITableListener 向您发送事件。
  • 感谢 Eric 和 Remy 的回复。我确实创建了一个类,但是我无法通过在帮助和在线中找到的示例来弄清楚如何做到这一点并让它发挥作用。我确实创建了一个类作为 TObject 的后代,我相信我也尝试过从 TInterfacedObject 下降。但是,接口调用特别需要 ITableListener 类型的参数。当我尝试通过我的课程时,它不会接受它,因为它是错误的类型。
  • 仅供参考,这是一个 .NET 后端;我不知道这会如何影响细节,但我认为我应该指出这一点。有人有例子吗?我尝试了很多不同的东西,但花了大约 8 个小时却无济于事......谢谢。
  • 到目前为止,在我能够找到的所有示例中,没有任何效果。底线是,传递的参数需要 dispinterface 类型;它不会采用任何其他类型。所以我再次问,你如何在 delphi 中实现/实例化一个调度接口?请举例。

标签: delphi com


【解决方案1】:

所以我浏览了the link 中提供的示例,并用你的接口替换了链接中的接口,并想出了这个:

ITableListener = dispinterface
  ['{83D42EA5-2C18-46EB-823B-262D62DF8CF1}']
  procedure Added(const rowID: WideString; const rowDataObj: IRow); dispid 1610743809;
  procedure Changed(const rowID: WideString; const rowDataObj: IRow); dispid 1610743810;
  procedure Deleted(const rowID: WideString; const rowDataObj: IRow); dispid 1610743811;
  procedure StatusChanged(status: TableStatus); dispid 1610743812;
end;

IMyTableListener = interface(IDispatch)
  ['{INSERT ARBITRARY GUID HERE}']
  procedure Added(const rowID: WideString; const rowDataObj: IRow); 
  procedure Changed(const rowID: WideString; const rowDataObj: IRow); 
  procedure Deleted(const rowID: WideString; const rowDataObj: IRow);
  procedure StatusChanged(status: TableStatus);
end;


TMyTableListener = class (TAutoObject, IMyTableListener)
public
  procedure Added(const rowID: WideString; const rowDataObj: IRow); 
  procedure Changed(const rowID: WideString; const rowDataObj: IRow); 
  procedure Deleted(const rowID: WideString; const rowDataObj: IRow);
  procedure StatusChanged(status: TableStatus);
end;

{ ... }
var
Disp: IDispatch;
Dispint: ITableListener;
{ ... }
// this may require that TMyTableListener is registered...
Disp := CreateComObject(TMyTableListener) as IDispatch;
// alternatively, try this (not sure about syntax):
Disp := new TMyTableListener as IDispatch;
Disp.AddRef();   // in C++, at least, creating the class via new() results in a 0 refcount, so you need to AddRef() so that releasing the object destroys the object appropriately...
Dispint := ITableListener(Disp);
subscribeUpdate(updateType, Dispint);
{ ... }

【讨论】:

  • 你打败了我,谢谢你。我已经实现了这一点。您对构造的第一个建议不起作用,因为 CreateComObject 将 TGUID 作为参数,而不是接口类。当我尝试使用第二种构造方法时,我收到错误“缺少 TFXTableListener 类的对象工厂”。
  • 这给了我一个“参数不正确”错误:code var disp: IDispatch; DispInt:ITableListener;类型库:ITypeLib;开始 CoInitializeEx(Nil,0); OleCheck(LoadRegTypeLib(LIBID_mytypelib_com,1,3,0,TypLib)); disp := TFXTableListener.Create(TypLib,DIID_ITableListener) 作为 IDispatch; disp._AddRef; DispInt := ITableListener(Disp); subscribeUpdate(TableUpdateType_Update,DispInt);
  • 在上面,TFXTableListener有一个声明如下:code TFXTableListener = class(TAutoIntfObject, IFXTableListener) public procedure Added(const rowID: WideString; const rowDataObj: IRow); procedure Changed(const rowID: WideString; const rowDataObj: IRow); procedure Deleted(const rowID: WideString; const rowDataObj: IRow); procedure StatusChanged(status: TableStatus); end;
  • 我不是 Delphi 大师,只是 COM 大师。据我所知,您已经实现了 dispinterface,它应该可以工作。你能确认你可以毫无错误地拨打DispInt.StatusChanged(TableUpdateType_Update)吗?如果可以,您已经实现了调度接口。在这一点上,我强烈建议选择VS Pro 的 90 天试用版,看看它是否真的在 VB 中有效
  • 这不起作用埃里克。如果我尝试运行 DispInt.StatusChanged(TableStatus_Initial),我会遇到访问冲突,因为它是一个事件,而不是我可以调用的方法(我猜)。 DispInt 是实例化的,所以此时我不知道哪个参数可能是错误的。谢谢。
【解决方案2】:

这个问题解决了。请参阅Troubleshooting COM error "The parameter is incorrect"

非常感谢@EricBrown 和@RemyLebeau 的帮助。

【讨论】:

    猜你喜欢
    • 2011-05-26
    • 2010-12-13
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 2020-06-04
    • 1970-01-01
    相关资源
    最近更新 更多