Passing array of struct from c# to delphi

后端 未结 1 781
北恋
北恋 2021-01-20 17:04

I am using Robert Giesecke Unmanaged Exports 1.2.6 in VS2010 and my goal is to pass an array of structs from c# (.NET 3.5)

相关标签:
1条回答
  • 2021-01-20 18:05

    Seems like I found the issue:

    The code runs fine if .NET 4.0 or higher is used. If you use .NET 3.5 or lower the len-parameter has to be passed by value.

    See MSDN-documentation SizeParamIndex v3.5:

    The parameter containing the size must be an integer that is passed by value.

    See MSDN-documentation SizeParamIndex v4.0:

    When arrays are passed as C-style arrays, the marshaler cannot determine the size of the array. Therefore, to pass an managed array to an unmanaged function or method, you must provide two arguments:

    • The array, defined by reference or value.

    • The array size, defined by reference or value.

    Code working with .NET 3.5:

    C#

    [DllExport]
    public static int func(
        [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
        Sample[] samples,
        int len,
        ref int outLen
    )
    {
        // len holds the length of the array on input
        // outLen is assigned the number of items that have been assigned values 
        // use the return value to indicates success and the required array size (>=0) or failure (<0)
        int requiredSize = 20;
        if (requiredSize < len)
        {
            len = requiredSize;
        }
        for (outLen = 0; outLen < len; outLen++)
        {
            samples[outLen].Name = "foo: " + outLen.ToString();
        }
        return requiredSize;
    }
    

    Delphi7

    function func(samples: PSample; len: Integer; var outLen: Integer): Integer; stdcall;
      external 'ArrayTest.dll';
    
    procedure Test2;
    var
      samples: array of TSample;
      i, len: Integer;
    begin
      len := 0;
      // query the required array size
      i := func(PSample(samples), len, len);
      if i>0 then
      begin
        len := i;
        SetLength(samples, len);
        if func(PSample(samples), len, len)>=0 then
          for i := 0 to len-1 do
            Writeln(samples[i].Name);
      end;
    end;
    

    Conclusion:

    The code posted in my question and posted by David Heffernan here only works with .NET >= 4.0! If you have to use .NET <= 3.5 you must pass the arraysize by value and not by reference!

    0 讨论(0)
提交回复
热议问题