将接口从delphi dll传输到vb.net

时间:2011-04-22 18:06:15

标签: vb.net delphi com

我有一个Delphi编写的DLL,它向vb.net应用程序公开了一些接口。 接口继承自IUnknown(但如果需要可以更改),简化示例:

  IWindow = interface(IUnknown)
    ['{E9A11D0B-8A05-4CBA-83FA-C5CC6818DF6E}']
    function GetCaption(var Caption: PChar): HRESULT; stdcall;
  end;

vb.net应用程序中的相同界面:

<ComImport(), Guid("E9A11D0B-8A05-4CBA-83FA-C5CC6818DF6E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface IWindow
    ReadOnly Property Caption() As <MarshalAs(UnmanagedType.LPWStr)> String
End Interface

一切正常。

现在我想将IWindow的集合转移到vb.net,在vb.net应用程序中,我希望能够通过for循环遍历它。

我读过可以使用IEnumerable / IEnumerator,但我不太明白如何实现它们。有没有关于此的好的教程,特别是双方的声明?示例代码会很棒。

请注意,我不想创建应该注册和导入的com dll。目前我导出的功能使我能够获得接口。

1 个答案:

答案 0 :(得分:0)

我有一个解决方案,但我并不完全满意。我把它放在这里作为答案,希望其他人的评论可以改进它,或者(甚至更好)将提供更好的答案。

我发现IEnumerator和IEnumerable的Delphi声明(Delphi 2010)没有使用stdcall调用约定所以我声明它们是这样的:

  IEnumerator = interface(IInterface)
  ['{496B0ABE-CDEE-11D3-88E8-00902754C43A}']
    function MoveNext: Boolean; safecall;
    function GetCurrent: IWindow; safecall;
    function Reset: HResult; stdcall;
  end;

  IEnumerable = interface(IInterface)
  ['{496B0ABE-CDEE-11D3-88E8-00902754C43A}']
    function GetEnumerator(var Enumerator: IEnumerator): HRESULT; stdcall;
  end;

我的集合接口继承自IEnumerable(但它有自己的GUID):

  IWindows = interface(IEnumerable)
  ['{D9174D5A-4946-4E5A-95B1-2CD521C3BF73}']
  end;

该类实现了IEnumerable,IEnumerator和IEnumVariant。 我认为我可以删除IEnumerator但我需要做更多测试才能确认。

  TIWindows = class(TInterfacedObject, IWindows, IEnumerable, IEnumVariant)

在VB.NET方面,它看起来像这样:

<ComImport(), Guid("D9174D5A-4946-4E5A-95B1-2CD521C3BF73"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface IWindows
    Inherits IEnumerable
    Shadows Function GetEnumerator() As IEnumerator
End Interface

我必须覆盖GetEnumerator,因为如果我不这样做,我会得到一个空引用异常,而在Delphi端,从不调用GetEnumerator()(VMT偏移问题?)。

主叫代码:

Dim Windows As IWindows
Dim Window As IWindow
Try
    Windows = Session.TopLevelWindows
    For Each Window In Windows
        TextBox1.Text = TextBox1.Text & Window.Caption
    Next
Catch ex As Exception
    ' Handle Exception
End Try

作为IWindow的Dim Windows需要使它工作,没有它我得到错误:“对象引用未设置为对象的实例。”

我尝试在vb.net端使用generic:

阴影函数GetEnumerator()As IEnumerator(Of IDNKWindow)

但是它给出了错误:无法编组“返回值”:通用类型无法编组。