找到你要的答案

Q:How to call .NET from Delphi? What I have tried so far? Avenues that I have looked into, but are not solutions

Q:如何从Delphi中调用.NET? 到目前为止我试了什么? 我所寻找的途径,但不是解决方案

THIS IS NOT A DUPLICATE

Duplicate marking note above ^ is wrong.

How can one invoke parametrised methods of a .NET library (not a registered COM object) from a Delphi 2010 program?

Specifically, I would like to access the Saxon API, as documented here. Specifically, I can create an XsltCompiler and read the BaseURI property, but not set it.

I have had some success using Win32 COM Server Objects (mscoree.dll and mscorlib.dll) and Late Binding. This is thanks to the example of the Project-Jedi TJclClrHost component. I can load .NET assemblies, create .NET objects and read simple string properties or functions without parameters. My question is how to pass parameters?

This question is exemplified by the task of how to set the Base URI of an XsltCompiler loaded from the Saxon .NET assembly. The API for BaseUri is documented here , the salient part of which is ...

public Uri BaseUri {get; set; }

Using reflection, I have determined that the name of the setter function is 'set_BaseUri'.

This method can be called using Late Binding/ Reflection from the type library imported from mscorlib.dll. The relevant method is listed below.

_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;

What I have tried so far?

In my Delphi 2010 program, I write ..

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

where: FType is of type _Type. args and modifiers are both a PSafeArray of length 1. modifiers is supposed to be an array of booleans to say if the argument is pass by reference or pass by value. In our case, this is an array of one boolean with a value of False (pass by value). args is supposed to be the array of actual parameter values.

I have tried all sorts of array element types, but I keep getting an error 'Specified array was not of the expected type.'

This is my code to set the args safeArray to some string.

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);
...

Avenues that I have looked into, but are not solutions

THIS IS NOT A DUPLICATE

ChrisF was wrong to mark this as a duplicate . The referenced question and answers refer only to situations where the developer controls and writes the .Net assembly. As stated, the assembly attempting to be invoked is a third party (Saxon). The question has been satisfactorily answered, but it should not have been closed as a duplicate.

THIS IS NOT A DUPLICATE

以上标记重复标记是错误的。

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

具体来说,我想访问这里记录的撒克逊API。具体地说,我可以创造一个xsltcompiler读baseURI属性的作用是:,但不放。

我已经成功使用Win32 COM服务器对象(mscoree.dll和mscorlib。DLL)和后期绑定。这是由于该项目的绝地tjclclrhost组件实例。我可以加载.NET程序集,创建.NET对象,并读取没有参数的简单字符串属性或函数。我的问题是如何传递参数?

这个问题的例子是任务如何设置一个xsltcompiler来自萨克森加载的基URI .NET组件。对于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);

where: FType is of type _Type. args and modifiers are both a PSafeArray of length 1. modifiers is supposed to be an array of booleans to say if the argument is pass by reference or pass by value. In our case, this is an array of one boolean with a value of False (pass by value). args is supposed to be the array of actual parameter values.

我已经尝试了各种数组元素类型,但我一直得到一个错误'指定数组不是预期类型。

这是我的代码来设置参数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);
...

我所寻找的途径,但不是解决方案

THIS IS NOT A DUPLICATE

ChrisF是标记这是一个重复的错误。引用的问题和答案仅指开发人员控制和写入.NET程序集的情况。如上所述,试图调用的程序集是三分之一方(撒克逊)。这个问题得到了圆满的答复,但不应该作为一个副本而被关闭。

answer1: 回答1:

Not terribly familiar with the Saxon API, but I am with Delphi, .NET and COM interoperability.

What I would suggest you do is create a facade pattern around the Saxon API in your favorite (or most tolerable) .NET language. Leave ComVisible True on those wrapper classes. Then access this wrapper assembly via COM Interop in Delphi.

You could really get away with an adapter patter, but since I am assuming you don't need to access the entire Saxon API then a facade is more appropriate.

不是非常熟悉的撒克逊API,但我与Delphi,NET和COM的互操作性。

我建议你做的是在你最喜欢的(或最可容忍的).NET API周围创建一个外观模式。NET语言。离开对真实的那些包装类。然后访问此包装组件通过COM互操作在Delphi。

你真的可以摆脱一个适配器模式,但是因为我假设你不需要访问整个撒克逊API然后门面更合适。

.net  delphi