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类型用于interop。因此,这里不能使用字符串和动态数组。
对于字符串,您需要在Delphi端使用PWideChar,指针指向以null结尾的宽字符数组。在C#端,如果将文本传递给Delphi,则使用字符串;如果文本指向另一个方向,则使用StringBuilder。
对于数组,您需要将参数/字段声明为指向元素类型的指针,然后使用指针算术遍历数组。编组器将按值传递指向数组中第一个元素的指针。
您需要在调用C#代码中分配所有缓冲区。如果您需要计算缓冲区的大小,请提供一个提供该信息的函数。
您的另一个问题是必须使这两个函数调用约定匹配。选择stdcall,这是C#端的默认值。并且您不能从Delphi DLL返回记录,因为Delphi对复杂的返回类型使用非标准ABI。您必须将记录作为var参数传递。
我怀疑marshaller不会处理包含非blitable结构数组的结构,即使您遵循了上面的建议,也会有这种情况。就我个人而言,我可能会要求一次只使用一个结构,以避免复杂的嵌套。在大纲中,将有一个名为GetItemCount的函数,它返回项目数。当然,还有一个名为GetItem的项目,它通过var参数返回了第i个项目。