gpt4 book ai didi

c# - 非托管导出/Delphi/.NET 4/Robert Giesecke

转载 作者:太空宇宙 更新时间:2023-11-03 13:55:22 31 4
gpt4 key购买 nike

我已经成功使用了 Roberts UnmanagedExportLibrary.zip从 Delphi 2007 调用 .NET 2/3.5 程序集。

但是,当我使用 VS2010 将 C# 程序集重新编译为目标 .NET 4 时,调用崩溃并在 ntdll.dll 中出现堆栈溢出异常。 (ntdll 调用 ntdll)加载 mscorlib/mscoreei 后。

在面向 .NET 4 时,还有其他人可以使用它吗? - 罗伯特的文档似乎暗示这应该有效。

顺便说一下,罗伯特的出色工作 - 非常有用。

谢谢迈尔斯。

最佳答案

数组更棘手,因为您需要更加注意数组的分配和销毁位置。最干净的方法总是在调用者处分配,将数组传递给被调用者让它填充数组。在您的上下文中,该方法看起来像这样:

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

需要指定数组需要在out方向编码。如果您希望值以两种方式编码,那么您将使用 In, Out 而不是 Out。您还需要将 MarshalAsUnmanagedType.LPArray 一起使用,以指示如何编码数组。而且您确实需要指定大小参数,以便编码器知道要编码回非托管代码的项目数。

然后在 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 [发现的][1](参见下面的评论),仅在 .net 4 上支持通过引用传递大小参数索引。在早期版本中,您需要通过值传递大小参数索引。

我在这里选择通过引用传递它的原因是允许以下协议(protocol):

  1. 调用者向传递一个指示数组大小的值。
  2. 被调用方传递一个值,指示已填充了多少元素。

这在 .net 4 上运行良好,但在早期版本上,您需要为步骤 2 使用额外的参数。

引用资料 https://stackoverflow.com/a/22507948/4339857

关于c# - 非托管导出/Delphi/.NET 4/Robert Giesecke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12415347/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com