Как позвонить .NET из Delphi?

ЭТО НЕ ДУБЛИКАТ

Повторяющееся примечание о маркировке выше ^ неверно.

Как можно вызвать параметризованные методы библиотеки .NET(не зарегистрированный COM-объект) из программы Delphi 2010?

В частности, я хотел бы получить доступ к Saxon API, как описано здесь. В частности, я могу создать XsltCompiler и прочитать свойство BaseURI, но не устанавливать его.

У меня был некоторый успех с использованием COM-объектов Win32 COM (mscoree.dll и mscorlib.dll) и Late Binding. Это объясняется примером компонента Project-Jedi TJclClrHost. Я могу загружать сборки .NET, создавать объекты .NET и читать простые строковые свойства или функции без параметров. Мой вопрос: как передать параметры?

Этот вопрос проиллюстрирован задачей о том, как установить базовый URI XsltCompiler, загруженный из сборки Saxon.NET. API для BaseUri документирован здесь, существенная часть которого...

public Uri BaseUri {get; set; }

Используя отражение, я определил, что имя функции setter является "set_BaseUri".

Этот метод можно вызвать с помощью Late Binding/Reflection из библиотеки типов, импортированной из 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 имеет тип _Type. args и modifiers являются и PSafeArray длины 1. Модификаторы должны быть массивом логических значений, чтобы сказать, передается ли аргумент по ссылке или передается по значению. В нашем случае это массив из одного логического значения со значением False (pass by value). 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. Как указано, сборка, пытающаяся быть вызванной, является третьей стороной (саксон). Вопрос был удовлетворительно дан, но он не должен был быть закрыт как дубликат.

Ответ 1

Не очень хорошо знаком с Saxon API, но я с Delphi,.NET и COM-совместимостью.

Я бы предложил вам создать фасадную схему вокруг Saxon API на вашем любимом (или наиболее переносимом) языке .NET. Оставьте ComVisible True на тех классах обертки. Затем зайдите в эту сборку через COM Interop в Delphi.

Вы действительно можете уйти с помощью адаптера адаптера, но поскольку я предполагаю, что вам не нужно обращаться ко всему Saxon API, тогда фасад более уместен.