gpt4 book ai didi

c# - 使用数组的非托管导出

转载 作者:行者123 更新时间:2023-11-30 22:20:31 26 4
gpt4 key购买 nike

我正在使用 RGiesecke DLLExport 库生成可以从 Delphi 动态加载的 C# DLL。我有一个像这样的方法:

[DllExport("GetVals", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
static void GetVals([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] valueList, int len)
{
valueList = new int[3];

int[] arrList = new int[] { 1, 2, 3 };
int idx = 0;

foreach (int s in arrList)
{
valueList[idx] = s;
idx++;
}
}

我希望能够从这个调用中返回一个数组,问题是我无法提前知道数组的大小,这只能在运行时确定。

为了测试我做了以下(也在 C# 中)

IntPtr hLibrary = NativeWinAPI.LoadLibrary(DLLFileName);
IntPtr pointerToFunction1 = NativeWinAPI.GetProcAddress(hLibrary, "GetVals");
if (pointerToFunction1 != IntPtr.Zero)
{
GetVals getfunction = (GetVals)Marshal.GetDelegateForFunctionPointer(pointerToFunction, typeof(GetVals));
int[] valList= null;
int fCnt = 3;
getfunction(valList, fCnt);
if (valList != null)
{

}
}

出现错误“正在尝试读取或写入 protected 内存”,这是可以理解的,因为我没有为调用者分配内存。在实际使用中,我不知道要返回的数组的大小,因此无法预分配内存。为了将最基本的东西放在那里,我试图简单地从 GetVals 返回一个未知大小的数组。

最佳答案

您必须以不受 GC 影响的方式分配数组。您可以使用 Marshal.AllocHGlobal 执行此操作:

[DllExport]
static void GetVals(out IntPtr unmanagedArray, out int length)
{
var valueList = new[]
{
1, 2, 3
};

length = valueList.Length;

unmanagedArray = Marshal.AllocHGlobal(valueList.Length * Marshal.SizeOf(typeof(int)));
Marshal.Copy(valueList, 0, unmanagedArray, length);
}

在 Delphi 端,您将获得指向第一个元素的指针和大小。要阅读它,您可以将指针 arraySize-1 递增并将其放入列表或 Delphi 管理的数组中:

uses
SysUtils,
Windows;

procedure GetVals(out unmanagedArray : PInteger; out arraySize : Integer);
stdcall;
external 'YourCSharpLib';

function GetValsAsArray : TArray<integer>;
var
unmanagedArray, currentLocation : PInteger;
arraySize, index : Integer;
begin
GetVals(unmanagedArray, arraySize);
try
SetLength(result, arraySize);
if arraySize = 0 then
exit;

currentLocation := unmanagedArray;

for index := 0 to arraySize - 1 do
begin
result[index] := currentLocation^;
inc(currentLocation);
end;
finally
LocalFree(Cardinal(unmanagedArray));
end;
end;

var
valuesFromCSharp : TArray<integer>;
index : Integer;
begin
valuesFromCSharp := GetValsAsArray();

for index := low(valuesFromCSharp) to high(valuesFromCSharp) do
Writeln(valuesFromCSharp[index]);
end.

关于c# - 使用数组的非托管导出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14934016/

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