2013-08-07 2 views
3

(Я понимаю, что это может быть дубликат, но я не понимаю, другие темы)Как маршалу Int Массивы или указатели на Int Массивы

Я работаю с C# У меня есть третья партия dll что В качестве параметров требуется int array (или указатели на int array). Как я могу объединить массив int между C# и C/C++? Эти функции объявлены следующим образом:

// 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); 

Будет ли это работать? Или как мне объявить эту функцию в C# в безопасном коде?

ответ

4

Это не 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=CallingConvention.StdCall по умолчанию, поэтому нет необходимости явно его выписывать.

Вы можете использовать этот путь:

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

ref int[] бы int** (но это может быть сложно пройти, потому что обычно вы ПОЛУЧАЕТЕ массив, а не SEND массива :-))

Обратите внимание, что ваш «интерфейс» довольно низок: вы не можете указать размеру вашего буфера, а также не можете получить необходимую длину буфера и не можете получить количество символов буфера, который действительно использовался.

+0

+1 для 'static extern void ReadStuff (int id, int [] buffer);' – dtb

0

Вы могли бы сделать что-то вроде этого:

[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, data, array.Length); 
} 

C++ код: (не проверено)

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

В качестве побочного элемента 'int * data = & array [0]' может быть сокращен как 'int * data = array' (как в C/C++) – xanatos

+0

Я бы предпочел избежать использования небезопасного кода. Я никогда не использовал его, и я не понимаю, зачем мне начинать. Также, как я уже сказал, это сторонняя DLL. Я не могу изменить подписи функций. – Bitterblue

+0

Я думаю, если вы хотите сообщить буфер/указатель на неуправляемый, вам понадобится небезопасная/исправленная –

Смежные вопросы