【问题标题】:How to call .NET from Delphi?如何从 Delphi 调用 .NET?
【发布时间】:2013-05-28 06:36:46
【问题描述】:

这不是重复的

^ 上面的重复标记注释是错误的。

如何从 Delphi 2010 程序调用 .NET 库(不是注册的 COM 对象)的参数化方法?

具体来说,我想访问 Saxon API,正如 here 所记录的那样。具体来说,我可以创建一个 XsltCompiler 并读取 BaseURI 属性,但不设置它。

我在使用 Win32 COM 服务器对象(mscoree.dll 和 mscorlib.dll)和后期绑定方面取得了一些成功。这要归功于 Project-Jedi TJclClrHost 组件的示例。我可以加载 .NET 程序集、创建 .NET 对象并读取简单的字符串属性或不带参数的函数。我的问题是如何传递参数?

这个问题的例子是如何设置从 Saxon .NET 程序集加载的 XsltCompiler 的 Base URI。 BaseUri 的 API 记录在 here 中,其中最突出的部分是...

public Uri BaseUri {get; set; }

使用反射,我确定setter函数的名称是'set_BaseUri'。

可以使用从mscorlib.dll 导入的类型库中的后期绑定/反射调用此方法。相关方法如下。

_Type = interface(IDispatch)
  ['{BCA8B44D-AAD6-3A86-8AB7-03349F4F2DA2}']
....
  function InvokeMember(const name: WideString; invokeAttr: BindingFlags; const Binder: _Binder; 
                      Target: OleVariant; args: PSafeArray; modifiers: PSafeArray; 
                      const culture: _CultureInfo; namedParameters: PSafeArray): OleVariant; safecall;
...
end;

到目前为止我尝试了什么?

在我的 Delphi 2010 程序中,我编写了 ..

FType.InvokeMember( 'set_BaseUri',
  BindingFlags_Public or BindingFlags_Instance or BindingFlags_InvokeMethod or
  BindingFlags_SetField or BindingFlags_SetProperty,
  nil, FInstance, args, modifiers, nil, nil);

在哪里: FType 的类型为 _Typeargsmodifiers 都是长度为 1 的 PSafeArray。修饰符应该是一个布尔数组,表示参数是按引用传递还是按值传递。在我们的例子中,这是一个布尔值数组,其值为 False(按值传递)。 args 应该是实际参数值的数组。

我尝试了各种数组元素类型,但一直收到错误消息“指定的数组不是预期的类型。”

这是我将 args safeArray 设置为某个字符串的代码。

var
  args: PSafeArray;
  argsbound: TSafeArrayBound;
  PassByRef: boolean;
  Idx: integer;
  OValue: OleVariant;
begin
Idx := 0;
argsbound.cElements := 1;
argsbound.lLbound   := 0;
args := SafeArrayCreate( VT_VARIANT, 1, argsbound);
OValue := 'www.abc.net.au';
SafeArrayPutElement( args, Idx, OValue);
...

我研究过但不是解决方案的途径

这不是重复的

ChrisF 将其标记为 duplicate 是错误的。引用的问题和答案仅涉及开发人员控制和编写 .Net 程序集的情况。如前所述,试图调用的程序集是第三方(Saxon)。该问题已得到令人满意的回答,但不应作为重复而关闭。

【问题讨论】:

  • 我想我会把它包装在 COM 或 UnmanagedExports 中。
  • @DavidHeffernan 感谢您的建议。在这种情况下无法使用 COM 包装器,因为 ComVisible 设置为 False。
  • 没有。您编写自己的 COM 包装器。

标签: .net delphi


【解决方案1】:

不太熟悉 Saxon API,但我熟悉 Delphi、.NET 和 COM 互操作性。

我建议您使用您最喜欢(或最容易接受的).NET 语言围绕 Saxon API 创建一个facade pattern。在这些包装类上保留 ComVisible True。然后在 Delphi 中通过COM Interop 访问这个包装程序集。

adapter patter 确实可以侥幸逃脱,但由于我假设您不需要访问整个 Saxon API,因此外观更合适。

【讨论】:

  • 谢谢吉姆。我希望有一个不那么痛苦的解决方案。
  • @SeanB.Durkin 由于最初的开发人员将 COM Visible 设置为 false,我相信他们已经把你画到了一个角落。您也许可以使用一些代码生成来加快速度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多