如何将整型数组或指向整型数组的指针进行序列化处理

6

(我知道这可能是重复的,但我不理解其他线程)

我正在使用C#,我有一个需要int数组(或int数组指针)作为参数的第三方dll。我如何在C#和C/C++之间传输int数组?函数声明如下:

// reads/writes int values from/into the array
__declspec(dllimport) void __stdcall ReadStuff(int id, int* buffer);

在C语言中,int*代表指针,那么我现在有些困惑,我是否需要使用IntPtr或者可以使用int[](更好)?我认为这样是可以的:
[DllImport(dllName)]
static extern void ReadStuff(int id, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] ref int[] buffer);

// call
int[] array = new int[12];
ReadStuff(1, ref array);

那会行吗?或者我需要如何在安全代码中声明这个函数?
2个回答

5

它不是一个 SafeArray。SafeArray 是与变量和旧版 OLE 相关的东西 :-) 它可能在词典中与 "渡渡鸟" 一词相邻。

它是:

[DllImport(dllName, CallingConvention=CallingConvention.StdCall)]
static extern void ReadStuff(int id, int[] buffer);

编组器将完成“正确”的事情。

或者

[DllImport(dllName, CallingConvention=CallingConvention.StdCall)]
static extern void ReadStuff(int id, IntPtr buffer);

但是使用起来会更加复杂。

CallingConvention.StdCall 是默认的调用约定,因此不需要显式地写出来。

您可以这样使用:

// call
int[] array = new int[12];
ReadStuff(1, array);

一个ref int[]将类似于int**(但是传递起来可能会比较复杂,因为通常你是接收数组而不是发送数组 :-) )请注意,您的“接口”非常差:您无法告诉ReadStuff缓冲区的长度,也不能接收缓冲区所需的长度,也没有办法接收实际使用的缓冲区字符数。

1
你可以这样做:
[DllImport(dllName)]
static extern void ReadStuff(int id, IntPtr buffer, int length);


int[] array = new int[12];

unsafe
{
  fixed (int* data = &array[0])
    ReadStuff(1, (IntPtr)data, array.Length);
}

C++代码:(未测试)

extern "C" __declspec(dllexport) VOID WINAPI ReadStuff(int id, int* buffer, int length);  

顺便提一下,int* data = &array[0] 可以缩写为 int* data = array(就像在 C/C++ 中一样)。 - xanatos
我宁愿避免使用不安全的代码。我从未使用过,也不明白为什么我应该开始使用。而且就像我说的,这是一个第三方DLL。我无法更改函数签名。 - Bitterblue
我认为,如果您想将缓冲区/指针传递给未托管代码,您需要使用unsafe/fixed。 - Jeroen van Langen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接