5

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

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

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

在 Cint*中将是一个指针,对吗?所以我很困惑是否必须使用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);

那行得通吗?或者我如何在 C# 中以安全代码声明这个函数?

4

2 回答 2

5

它不是 SafeArray。SafeArray 与变体和 OLE 的美好旧时光有关 :-) 它可能存在于字典中“dodo”一词附近。

这是:

[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=CallingConvention.StdCall是默认的,所以没有必要明确地写出来。

你用这种方式:

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

Aref int[]将是 a int**(但传递可能很复杂,因为通常您接收数组,而不是发送数组:-))

请注意,您的“界面”很差:您无法判断ReadStuff缓冲区的长度,也无法接收到必要的缓冲区长度,也无法接收到实际使用的缓冲区字符数。

于 2013-08-07T12:49:38.213 回答
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);  
于 2013-08-07T12:47:20.767 回答