如何使用非托管导出将结构数组从.net传递到Delphi (Robert Giesecke)
本文关键字:net Delphi Giesecke Robert 数组 何使用 结构 | 更新日期: 2023-09-27 17:50:53
我刚刚询问并获得了我的问题的答案:"无法返回自定义类型实例与非托管导出(Robert Giesecke)"->不能't返回非托管导出的自定义类型实例(Robert Giesecke)我想知道是否(以及如何)可以使用非托管导出(Robert Giesecke)将结构数组从。net传递到Delphi:
- 直接返回数组,如
[DllExport] public static void CreateSampleInstance(out Sample[] sample)
- 在返回的结构体 中使用数组成员
[DllExport] public static void CreateSampleInstance(out Sample sample)
和
`public struct Sample
{
Other[] Others;
}`
我的问题是如何编写Delphi端以及在。net端设置什么属性。
数组比较棘手,因为您需要更加注意数组的分配和销毁位置。最简洁的方法总是在调用者处分配,将数组传递给调用者,让它填充数组。该方法在您的上下文中看起来像这样:
public struct Sample
{
[MarshalAs(UnmanagedType.BStr)]
public string Name;
}
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
Sample[] samples,
ref int len
)
{
// len holds the length of the array on input
// len is assigned the number of items that have been assigned values
// use the return value to indicate success or failure
for (int i = 0; i < len; i++)
samples[i].Name = "foo: " + i.ToString();
return 0;
}
您需要指定数组需要在输出方向上编组。如果您希望以两种方式编组值,那么您将使用In, Out
而不是Out
。您还需要使用MarshalAs
和UnmanagedType.LPArray
来指示如何封送数组。您确实需要指定size参数,以便编组程序知道要将多少项封送回非托管代码。
然后在Delphi端像这样声明函数:
type
TSample = record
Name: WideString;
end;
PSample = ^TSample;
function func(samples: PSample; var len: Integer): Integer; stdcall;
external dllname;
这样写:
var
samples: array of TSample;
i, len: Integer;
....
len := 10;
SetLength(samples, len);
if func(PSample(samples), len)=0 then
for i := 0 to len-1 do
Writeln(samples[i].Name);
AlexS发现(见下面的注释),通过引用传递size参数索引只支持。net 4。在较早的版本中,您需要按值传递size参数索引。
我选择在这里通过引用传递它的原因是为了允许以下协议:
- 调用者在中传递一个值,指示数组的大小。
- 被调用方将传递出一个值,该值表示已填充了多少元素。
这在。net 4中工作得很好,但在早期版本中,您需要在步骤2中使用额外的参数