Возвращение строки из DLL C# с неуправляемым экспортом в сценарий Inno Setup
У меня есть C# DLL, которая предоставляет функцию с использованием неуправляемого экспорта, которая вызывается непосредственно сценарием Inno Setup Pascal. Эта функция должна вернуть строку в Inno Setup. Мой вопрос: как я могу это сделать?
Мой предпочтительный метод - передать буфер из Inno Setup в функцию C#, которая будет возвращать строку внутри этого буфера. Я пришел с этим кодом:
C# функция:
[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
static int Test([Out, MarshalAs(UnmanagedType.LPWStr)] out string strout)
{
strout = "teststr";
return strout.Length;
}
Сценарий установки Inno:
function Test(var res: String):Integer; external 'Test@files:testdll.dll stdcall';
procedure test1;
var
Res: String;
l: Integer;
begin
SetLength(Res,256);
l := Test(Res);
{ Uncommenting the following line causes an exception }
{ SetLength(Res,l); }
Log('"Res"');
end;
Когда я запускаю этот код Res
переменная пуста (я вижу "" в журнале)
Как я могу вернуть строку из этой DLL?
Обратите внимание, что я использую версию Inno Setup для Unicode. Я также не хочу использовать COM для вызова этой функции, а также для выделения буфера в DLL и возврата его в Inno Setup.
1 ответ
Я бы предложил вам использовать BSTR
тип, который используется как тип данных для вызовов функций взаимодействия. На вашей стороне C# вы бы маршаллировали свою строку как UnmanagedType.BStr
введите и на стороне Inno Setup вы будете использовать WideString
, который совместим с BSTR
тип. Таким образом, ваш код будет изменен на это (см. Также Marshalling sample
глава неуправляемого экспорта документов):
[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
static int Test([MarshalAs(UnmanagedType.BStr)] out string strout)
{
strout = "teststr";
return 0; // indicates success
}
И на стороне Inno Setup с использованием WideString
к этому:
[Code]
function Test(out strout: WideString): Integer;
external 'Test@files:testdll.dll stdcall';
procedure CallTest;
var
retval: Integer;
str: WideString;
begin
retval := Test(str);
{ test retval for success }
Log(str);
end;