breez breez - 2 months ago 30
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:

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

Answer

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:

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.