Неуправляемый код C в C # Marshalling с помощью массива ref! - PullRequest
1 голос
/ 14 августа 2010

У меня действительно тяжелое время, чтобы упустить этот маршаллинг.

У меня неуправляемый код, который выглядит следующим образом:

WORD HLP_GetDeviceNames (LPSTR *DevNames, WORD Max_Len, WORD Max_Num)

Просто к вашему сведению, я не писал этот неуправляемый код, но должениспользуй это.

Возвращает: WORD, указывающее на ошибку.

DevNames: Указатель на массив массивов символов.В основном массив строк, которые будут изменены и возвращены мне!

Max_Len: длина каждой строки (мне сказали, что это должно быть 256)

Max_Num: длина массива.Я использую другой работающий вызов Invoke, который сообщает мне количество устройств, поэтому я точно знаю, сколько строк отправить.

Я использовал взаимодействие P / Invoke signatureToolkit, чтобы выяснить многое из этого, но также прочитал кучучтобы получить еще дальше.Где я сейчас нахожусь здесь:

[DllImport("UsbMeasLib.dll")]
public static extern ushort HLP_GetDeviceNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] ref StringBuilder[] DevNames, ushort Max_Len, ushort Max_Num);

Я называю свой код следующим образом:

StringBuilder[] DevNames = new StringBuilder[deviceCount];
     for(int i = 0; i< deviceCount; i++)
     {
           DevNames[i] = new StringBuilder().Append(' ', 256);
     }

     HachUsbMeasLib.HLP_GetDeviceNames(ref DevNames, 256, Convert.ToUInt16(DevNames.Count())); 

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

Когда я запускаю код, мой массив не изменяется!

Я не совсем уверен, что происходит, но я думаю, что это имеетчто-то связанное с тем, что CLR говорит неуправляемому коду не изменять мой массив на месте, а создает новую ссылку (указатель).Даже если это так, я не знаю, как это исправить.

Спасибо за любые идеи, которые кто-либо может предложить!

Ответы [ 2 ]

2 голосов
/ 16 августа 2010

Попробуйте работать на низком уровне. Объявите параметр DevNames как IntPtr []. Подготовьте его следующим образом:

IntPtr[] devNames = new IntPtr[deviceCount];

for(int i = 0; i < deviceCount; i++) 
{ 
    devNames[i] = Marshal.AllocHGlobal[256];
}

Передайте этот массив HLP_GetDeviceNames. Для обработки выходных данных примените Marshal.PtrToStringAnsi к каждому члену DevNames. Не забудьте выпустить DevNames [i] с Marshal.FreeHGlobal в конце.

0 голосов
/ 17 августа 2010

Я понял это.Спасибо всем, кто ответил.

Я узнал, как это работает.Я просто предоставляю пространство памяти, но я должен сообщить маршалгу, что я ожидаю вход и выход с этим объектом, чтобы он позволял неуправляемому коду изменять выделенное пространство.

Я сделал это так:

[DllImport("UsbMeasLib.dll")]
private static extern ushort HLP_GetDeviceNames([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] DevNames, ushort Max_Len, ushort Max_Num);

Я использую строку вместо построителя строк, потому что неуправляемый код просто заменит строку, что нормально.Я получаю указатель массива обратно, а не измененные строки.управляемый код просто изменяет массив указателей для указания на новые строковые объекты (я думаю).

int numDev = HLP_GetNumDevices();


string[] names = new string[numDev];

for (int i = 0; i < names.Length; i++)
{
    names[i] = new StringBuilder().Append(' ', 256).ToString();
}

ushort errorCode = HLP_GetDeviceNames(names, 256, Convert.ToUInt16(numDev));

Я выделяю память для неуправляемого кода, а затем позволяю неуправляемому коду изменять строки там.

Это работает, но я не знаю, есть ли у меня потенциальные утечки памяти или другие потенциальные проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...