Как позвонить .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, тогда фасад более уместен.