我如何通过使用非托管的出口(罗伯特捷)从.NET结构的阵列德尔福? [英] How do I pass arrays of struct from .NET to Delphi using unmanaged export (Robert Giesecke)?

查看:191
本文介绍了我如何通过使用非托管的出口(罗伯特捷)从.NET结构的阵列德尔福?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚才问及得到的回答我的疑问是:不能返回定制与非托管的出口(罗伯特捷)类型的实例 - > <一个href=\"http://stackoverflow.com/questions/22503718/cant-return-custom-type-instance-with-unmanaged-export-robert-giesecke\">can't返回定制与非托管的出口类型实例(罗伯特捷)
我不知道是否(以及如何),可以使用非托管的出口从.NET通过结构的阵列德尔福(罗伯特捷):

I have just asked and obtained an answer to my question that was : "can't return custom type instance with unmanaged export (Robert Giesecke)" -> can't return custom type instance with unmanaged export (Robert Giesecke) I wonder if (and how) it is possible to pass arrays of struct from .NET to Delphi using unmanaged export (Robert Giesecke):


  • 直接好像回到阵列

[DLLEXPORT]公共静态无效CreateSampleInstance(出样品[]样品)


  • 使用数组成员在返回的结构

[DLLEXPORT]公共静态无效CreateSampleInstance(样品出样)

`public struct Sample
{
   Other[] Others;
}`

我在这里的问题是如何写的Delphi侧,什么属性在.NET一体。

My question here is how to write the Delphi side and what attribute to set in the .NET one.

非常感谢。

推荐答案

数组是更棘手的,因为你需要采取更多的照顾,其中阵列分配和销毁了。最简洁的方法总是在调用者来分配,数组传递给被叫方让其填写的阵列。这种方法看起来像这样在上下文:

Arrays are more tricky because you need to take more care over where the array is allocated and destroyed. The cleanest approach is always to allocate at the caller, pass the array to the callee to let it fill out the array. That approach would look like this in your context:

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;
}

您需要指定数组需要在出方向进行编组。如果你想编组两种方式,那么你会使用输入,输出而不是值。你还需要使用的MarshalAs UnmanagedType.LPArray 来指示如何封送数组。而你确实需要这样的编组知道有多少项目编组回非托管code指定大小参数。

You need to specify that the array needs to be marshalled in the out direction. If you wanted values marshalled both ways then you would use In, Out instead of Out. You also need to use MarshalAs with UnmanagedType.LPArray to indicate how to marshal the array. And you do need to specify the size param so that the marshaller knows how many items to marshal back to the unmanaged code.

然后在德尔福方声明是这样的功能:

And then on the Delphi side you declare the function like this:

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 发现(见下面的注释),通过引用传递的大小参数指标只支持.NET 4 。在早期的版本,则需要按值传递的大小参数指标。

As AlexS discovered (see comments below), passing the size param index by reference is only supported on .net 4. On earlier versions you need to pass the size param index by value.

我选择参照这里传递它的原因是允许下列协议:

The reason I chose to pass it by reference here is to allow for the following protocol:


  1. 调用者传递的的指示阵列多大的值。

  2. 被叫通过的的说明有多少元素的值已填充。

  1. The caller passes in a value indicating how large the array is.
  2. The callee passes out a value indicating how many elements have been populated.

这行之有效的.NET 4中,但在早期版本中,你需要使用一个额外的参数步骤2。

This works well on .net 4, but on earlier versions you would need to use an extra parameter for step 2.

这篇关于我如何通过使用非托管的出口(罗伯特捷)从.NET结构的阵列德尔福?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆