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;
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);
...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With