breez breez - 3 months ago 41
C# Question

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:

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

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

For some reason,
is always 0 and
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.


The UnmanagedType.LPArray with string maps to an array of pointer 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:

  TArrayOfPAnsiChar = array of PAnsiChar;

procedure DummyMethod(out StringPtrs: TArrayOfPAnsiChar; out Count: Integer);
  external 'DummyMethod@files:ArrayInno.dll stdcall';

function DummyMethodWrapper: TArrayOfString;
  ArrayOfPAnsiChar: TArrayOfPAnsiChar;
  I, Count: Integer;
  DummyMethod(ArrayOfPAnsiChar, Count);

  SetArrayLength(Result, Count);
  for I := 0 to Count - 1 do
    Result[I] := ArrayOfPAnsiChar[I];

(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.