Search code examples
c#inno-setupdllexportpascalscript

Returning a string array from C# to Inno Setup


I'm using Unmanaged Exports NuGet from Robert Giesecke and have the following method in C#:

[DllExport("DummyMethod", CallingConvention = CallingConvention.StdCall)]
public static void DummyMethod(
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out string[] test, out int count)
{
    count = 3;
    test = new[] {"test1", "test2", "test3"};
}

In Inno Setup this is my code:

[Code]
procedure DummyMethod(out Test: TArrayOfString; out Count: Integer);
external 'DummyMethod@files:MyDll.dll stdcall';

procedure InitializeWizard();
  var Test : TArrayOfString;
  var Count : Integer;
begin
  DummyMethod(Test, Count);
  MsgBox(Test[0], mbError, MB_OK);
end;

For some reason, Count is always 0 and Test is always empty.

I have taken a look at several examples but couldn't find one where Inno Setup fetches a string array from a C# DLL.


Solution

  • The UnmanagedType.LPArray with string maps to an array of pointers to char (C-style char**). In Unicode Pascal Script that's array of PAnsiChar. There's no way the Pascal Script can magically convert that to TArrayOfString (array of string).

    You can convert it like this:

    type
      TArrayOfPAnsiChar = array of PAnsiChar;
    
    procedure DummyMethod(out StringPtrs: TArrayOfPAnsiChar; out Count: Integer);
      external 'DummyMethod@files:ArrayInno.dll stdcall';
    
    function DummyMethodWrapper: TArrayOfString;
    var
      ArrayOfPAnsiChar: TArrayOfPAnsiChar;
      I, Count: Integer;
    begin
      DummyMethod(ArrayOfPAnsiChar, Count);
    
      SetArrayLength(Result, Count);
      for I := 0 to Count - 1 do
      begin
        Result[I] := ArrayOfPAnsiChar[I];
      end;
    end;
    

    (Tested with Unicode Inno Setup)


    Side notes:

    • It's not clear, who does a memory allocation for the TArrayOfAnsiChar and individual character arrays. I smell a memory leak, at best.
    • You probably want to use 16-bit character buffer, not 8-bit character buffer to allow full Unicode. Though note that this is more difficult to implement in the Pascal Script as it lacks 16-bit character pointer type.