Delphi DLL函数向C#应用程序返回一个带有打开数组的记录

本文关键字:一个 记录 数组 函数 DLL 应用程序 返回 Delphi | 更新日期: 2023-09-27 18:28:37

因此,我在从C#调用的Delphi DLL中有以下记录结构。

  TItemPic = record
    x, y : Integer;
    id : Integer;
    Hue : Integer;
    Page : Integer;
    ElemNum : Integer;
  end;
  TItemToken =  record
    id : Cardinal;
    Arguments : String;
    ElemNum : Integer;
  end;

  TItemType = record
    ID : Integer;
    Hue : Integer;
    ItemPics : array of TItemPic;
    ItemToken : array of TItemToken;
end;

和功能:

function GetItemInfo(index : Word) : TItemType;

现在我在C#中有以下翻译的结构:

    public struct TItemPic
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int ID { get; set; }
        public int Hue { get; set; }
        public int Page { get; set; }
        public int ElemNum { get; set; }
    }
    public struct TItemToken
    {
        public uint ID  { get; set; }
        public TPCharStr Arguments { get; set; }
        public int ElemNum { get; set; }
    }
    public struct TItemType
    {
        public uint ID { get; set; }
        public int Hue { get; set; }
        public TItemPic[] ItemPics { get; set; }
        public TItemToken[] ItemToken { get; set; }
    }

[DllImport("mydelphi.dll", EntryPoint = "GetItemInfo", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
internal static extern TItemType GetItemInfo(ushort index);

目标是:

TItemType myItem = GetItemInfo(1);

我不确定如何处理TItemType记录ItemPics : array of TItemPic;ItemToken : array of TItemToken; 中的开放数组

阅读了David Heffernan的一些答案,我认为我可能应该将这些声明为IntPtr,然后将数据复制到数组中——然而,我不确定如何获得存储的元素数量。他指出,Delphi开放数组在传递的指针的负偏移量处存储引用计数和数组大小。。。但我不确定如何检索这些信息并将其转换:-)

Delphi DLL函数向C#应用程序返回一个带有打开数组的记录

首先,这些是动态数组,而不是开放数组。

不能将托管Delphi类型用于interop。因此,这里不能使用字符串和动态数组。

对于字符串,您需要在Delphi端使用PWideChar,指针指向以null结尾的宽字符数组。在C#端,如果将文本传递给Delphi,则使用字符串;如果文本指向另一个方向,则使用StringBuilder。

对于数组,您需要将参数/字段声明为指向元素类型的指针,然后使用指针算术遍历数组。编组器将按值传递指向数组中第一个元素的指针。

您需要在调用C#代码中分配所有缓冲区。如果您需要计算缓冲区的大小,请提供一个提供该信息的函数。

您的另一个问题是必须使这两个函数调用约定匹配。选择stdcall,这是C#端的默认值。并且您不能从Delphi DLL返回记录,因为Delphi对复杂的返回类型使用非标准ABI。您必须将记录作为var参数传递。

我怀疑marshaller不会处理包含非blitable结构数组的结构,即使您遵循了上面的建议,也会有这种情况。就我个人而言,我可能会要求一次只使用一个结构,以避免复杂的嵌套。在大纲中,将有一个名为GetItemCount的函数,它返回项目数。当然,还有一个名为GetItem的项目,它通过var参数返回了第i个项目。