Оболочка c # для DLL c - PullRequest
2 голосов
/ 02 июня 2010

Я пытаюсь написать оболочку, чтобы мое приложение на C # могло использовать DLL, написанную на C. Вот определение метода, которое я пытаюсь обернуть:

void methodA(const uint32_t *data); //c header declaration

Проблема, с которой я столкнулся, заключается в попытке выяснить, как дать эквивалентный указатель из c #. В c # я хочу, чтобы он работал на:

 UInt32 data[]  //my c# object i want to be able to pass in

но как мне дать эквивалентный указатель в моей оболочке? Я пробовал

ref data //my attempt at giving an equivalent pointer to the DLL

но это, похоже, не работает. Используя операторы отладки в DLL, я вижу, что получаемые таким образом значения не являются тем, что я пытаюсь передать.

Итак, мой вопрос сводится к тому, чтобы я правильно обернул функцию c, использующую указатель для ссылки на массив?

Ответы [ 2 ]

3 голосов
/ 02 июня 2010

Массив уже является ссылкой, поэтому он будет выделен как указатель на него. Это должно работать:

[DllImport("my.dll")]
static extern void methodA(UInt32[] data);

Если вам нужно передать данные обратно в управляемый код, вам нужно украсить параметр атрибутом Out :

[DllImport("my.dll")]
static extern void methodA([In, Out] UInt32[] data);

Использование:

uint[] data = new uint[] { 1, 2, 3, 4, 5 };
methodA(data);
Console.WriteLine(data[0]);

Другое решение заключается в объявлении параметра типа IntPtr:

[DllImport("my.dll")]
static extern void methodA(IntPtr data);

Чтобы это работало, вам нужно закрепить массив, чтобы получить для него IntPtr, или выделить память в неуправляемом пространстве и скопировать в нее содержимое массива. Я бы не рекомендовал эти варианты.


ref требуется, если вы хотите передать одно значение типа значения по ссылке:

[DllImport("my.dll")]
static extern void methodB(ref UInt32 data);
1 голос
/ 02 июня 2010

Объявите methodA с параметром IntPtr в объявлении P / Invoke. Чтобы преобразовать массив UInt32 в неуправляемый массив, используйте метод Marshal.Copy (Int32 [], Int32, IntPtr, Int32) .

Пример кода из этой статьи подходит для вас, вызовите methodA после этой строки:

Marshal.Copy(managedArray, 0, pnt, managedArray.Length);
// now call methodA with pmt parameter
...