Возвращение строки из 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;
Другие вопросы по тегам