2
votes

I want to use delphi array function in C#.

My delphi code:

TIntegerArray = array of integer;
function Testarray(): TIntegerArray stdcall; export;
 var
   res: TIntegerArray2;
 begin
   SetLength(res, 10);
   res[5] := 55;
   Result := res;
 end;
 exports Testarray;

C# code:

[DllImport("GitaTele.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int[] Testarray();

Shows me error:

Cannot marshal 'return value': Invalid managed/unmanaged type combination.

1
In Delphi you return a specific type TIntegerArray2 while in C# you try to map this to int[]. Howe is this supposed to work?Quality Catalyst
You can't marshal directly an array as the retun value. And even if you could, who would free the memory Delphy allocated for that array?xanatos
thank you. edited.my code is more than: TIntegerArray = array of integer; TIntegerArray2 = array of integer;Ali Yousefi
You cannot use arrays as a function result across DLL boundaries. Simple as that. Same reason why you cannot return strings as function results.Jerry Dodge
Pass it as a var parameter instead. But it's not as simple as that. You also have to decide which side is responsible for memory allocation / freeing. The answer varies depending on that.Jerry Dodge

1 Answers

3
votes

Delphi dynamic arrays are not valid interop types. You need to have the caller allocate the array, and then let the callee populate it.

procedure PopulateArray(arr: PInteger; var len: Integer); stdcall;
var
  i: Integer;
  returnArray: TArray<Integer>;
begin
  returnArray := GetArray;
  len := Min(len, Length(returnArray));
  for i := 0 to len - 1 do
  begin
    arr^ := returnArray[i];
    inc(arr);
  end;
end;

Do note the export has no meaning, is ignored, and should be removed for sake of simplicity.

From C# the calling code is:

[DllImport("...", CallingConvention = CallingConvention.StdCall)]
public static extern void PopulateArray(
    [In, Out]
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
    int[] arr,
    ref int len
);

....

int[] arr = new int[50];
int len = arr.Length;
PopulateArray(arr, ref len);
// len now contains actual length