我正在尝试与 nethost.dll 进行互操作,但它不断返回一个非零整数,这表明失败。我对 C# 中的本机互操作不太熟悉,所以我很难诊断问题。
互操作代码如下,使用 ClangSharpPInvokeGenerator 生成:
[DllImport("runtimes/win-x64/nethost.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)]
public static extern int get_hostfxr_path(ushort* buffer, nuint* buffer_size, get_hostfxr_parameters* parameters);
public unsafe partial struct get_hostfxr_parameters
{
public nuint size;
public ushort* assembly_path;
public ushort* dotnet_root;
}
互操作代码由下面的代码调用,基于Microsoft 的托管指南中提供的示例:
ushort* ptr = stackalloc ushort[ushort.MaxValue];
nuint* size = stackalloc nuint[ushort.MaxValue / sizeof(ushort*)];
int i = nethost.get_hostfxr_path(ptr, size, null);
返回后,传递的缓冲区不会更改调用
get_hostfxr_path
之前设置的值。整数返回为 -2147450728
。
我尝试将 PInvoke 的
buffer
和 buffer_size
参数更改为 IntPtr
。它仍然有效,但错误代码没有改变。我还查看了其他开源项目中存在的互操作代码,但我无法找到另一种编写我的代码的方法。
我到底错过了什么?我真的很感激你的帮助,我已经超出了我的能力范围并且陷入困境。
您收到的错误是 HostApiBufferTooSmall,因为您传递了无效大小的缓冲区。您的
size
参数是指向包含垃圾的数组的指针。你可以这样修复它:
ushort* ptr = stackalloc ushort[ushort.MaxValue];
nuint* size = stackalloc nuint[1];
*size = ushort.MaxValue;
var hr = get_hostfxr_path(ptr, size, null);
此外,您可以使用
ushort
,但使用 .NET 的自然 char
和 string
类型更容易,这应该可以工作:
const int bufferSize = 2048; // or ushort.MaxValue but seems too large
var str = new string('\0', bufferSize);
var size = bufferSize / sizeof(char);
fixed (char* buffer = str)
{
var hr = get_hostfxr_path(buffer, (nuint*)&size, null);
if (hr >= 0)
{
str = str[..(size - 1)]; // final string
}
}