C# 如何使用非托管导出(Robert Giesecke)将dateTime类型数组从.NET传递到Delphi?

C# 如何使用非托管导出(Robert Giesecke)将dateTime类型数组从.NET传递到Delphi?,c#,arrays,delphi,datetime,C#,Arrays,Delphi,Datetime,我想将dateTime类型数组从.NETDLL传递到Delphi。 这是c代码: 但是Marshal.Copy()方法不支持指向非托管内存指针的DateTime类型数组。我该怎么办?此外,如何实现delphi代码?如果您的日期时间值在自动化兼容范围内,您可以使用以获取自动化兼容值,然后只需使用封送的重载。使用双[]复制: public static void ReadDateTimeData(out IntPtr unmanagedArray, out int length) { //

我想将dateTime类型数组从.NETDLL传递到Delphi。 这是c代码:


但是Marshal.Copy()方法不支持指向非托管内存指针的DateTime类型数组。我该怎么办?此外,如何实现delphi代码?

如果您的日期时间值在自动化兼容范围内,您可以使用以获取自动化兼容值,然后只需使用
封送的重载。使用
双[]
复制

public static void ReadDateTimeData(out IntPtr unmanagedArray, out int length)
{
    // Get the DateTimeArray
    DateTime[] dateTimeArray = GetDateTimeArray();
    length = dateTimeArray.Length;
    // Convert to double[]
    double[] oaDateArray = new double[length];
    for (int i = 0; i < length; i++)
        oaDateArray[i] = dateTimeArray[i].ToOADate();

    unmanagedArray = Marshal.AllocHGlobal(length * Marshal.SizeOf(typeof(double)));
    Marshal.Copy(oaDateArray, 0, unmanagedArray, length);
}
或者,在范围检查关闭的情况下:

type
  PDateTimeArray = ^TDateTimeArray;
  TDateTimeArray = array[0..0] of TDateTime;

procedure ReadDateTimeData(out DateTimeArray: PDateTimeArray; out Length: Integer); stdcall; external 'TestLib.dll';
procedure FreeDateTimeData(DateTimeArray: PDateTimeArray); stdcall; external 'TestLib.dll';

procedure Main;
var
  DateTimeArray: PDateTimeArray;
  I, Len: Integer;
begin
  ReadDateTimeData(DateTimeArray, Len);
  try
    for I := 0 to Len - 1 do
      Writeln(DateTimeToStr(DateTimeArray^[I]));
  finally
    FreeDateTimeData(DateTimeArray);
  end;
end;

您需要就日期互操作类型达成一致。C#DateTime不同于Delphi TDateTime。您可以将C#转换为相当于Delphi日期时间的双精度。如果是我,我可能会选择Unix时间的64位整数。你能不能简单地传递一个字符串编组数组并在delphi端转换回日期?@toby这是可能的,但用字符串表示日期有点不雅观。此外,字符串数组比值类型数组更难封送。当以字符串形式传递日期/时间值时,应该用于互操作。这是一种很好的方法。FWIW
FreeDateTimeData
不需要导出。您只需在Delphi端调用
LocalFree
,因为
marshall.AllocHGlobal
只是调用
LocalAlloc
@DavidHeffernan谢谢,这很有趣。但是上面写着“返回值:指向新分配内存的指针。必须使用Marshal.FreeHGlobal方法释放此内存。”注释说:此方法从Kernel32.dll公开Win32 LocalAlloc函数。它旨在用于互操作,因此了解从哪个共享堆分配它很有用。另一个选项是
Marshal.CoTaskMemAlloc
,它在COM堆外进行分配。因此,您可以使用COM的
CoTaskMemAlloc
CoTaskMemFree
以及其他COM堆方法来分配/释放这样的内存。@DavidHeffernan是的,但由于它们如此明确地要求使用
Marshal.FreeHGlobal
,我想知道CLR除了调用
LocalAlloc
之外是否还做了什么,例如,在内部跟踪分配的内存。不过,只是猜测而已。为了以防万一,我更愿意导出另一个函数。不,它是
LocalAlloc
的直接包装。它的全部意义在于它是一个共享堆。如果CLR做得更多,那么它几乎是无用的。导出一个函数,如果你愿意,我只是指出这一点,以防你还不知道。
procedure ReadDateTimeData(out DateTimeArray: PDateTime; out Length: Integer); stdcall; external 'TestLib.dll';
procedure FreeDateTimeData(DateTimeArray: PDateTime); stdcall; external 'TestLib.dll';

procedure Main;
var
  DateTimeArray, P: PDateTime;
  I, Len: Integer;
begin
  ReadDateTimeData(DateTimeArray, Len);
  try
    P := DateTimeArray;
    for I := 0 to Len - 1 do
    begin
      Writeln(DateTimeToStr(P^));
      Inc(P);
    end;
  finally
    FreeDateTimeData(DateTimeArray);
  end;
end;
type
  PDateTimeArray = ^TDateTimeArray;
  TDateTimeArray = array[0..0] of TDateTime;

procedure ReadDateTimeData(out DateTimeArray: PDateTimeArray; out Length: Integer); stdcall; external 'TestLib.dll';
procedure FreeDateTimeData(DateTimeArray: PDateTimeArray); stdcall; external 'TestLib.dll';

procedure Main;
var
  DateTimeArray: PDateTimeArray;
  I, Len: Integer;
begin
  ReadDateTimeData(DateTimeArray, Len);
  try
    for I := 0 to Len - 1 do
      Writeln(DateTimeToStr(DateTimeArray^[I]));
  finally
    FreeDateTimeData(DateTimeArray);
  end;
end;