11

这不是重复的

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

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

具体来说,我想访问 Saxon API,如此所述。具体来说,我可以创建一个 XsltCompiler 并读取 BaseURI 属性,但不设置它。

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

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

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是 类型_Typeargs并且modifiers都是长度为 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 将其标记为重复是错误的。引用的问题和答案仅涉及开发人员控制和编写 .Net 程序集的情况。如前所述,试图调用的程序集是第三方(Saxon)。该问题已得到令人满意的回答,但不应作为重复而关闭。

4

1 回答 1

3

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

我建议你做的是用你最喜欢的(或最能容忍的).NET 语言围绕 Saxon API创建一个外观模式。在这些包装类上保留 ComVisible True。然后通过Delphi 中的COM Interop访问这个包装程序集。

您真的可以使用适配器模式,但由于我假设您不需要访问整个 Saxon API,因此外观更合适。

于 2013-06-04T03:35:23.763 回答