Вопрос

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

У меня есть Umaned код, который выглядит так:

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

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

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

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

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

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

Я использовал P / Invoke Interop 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())); 

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

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

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

Спасибо за любой взгляд, кто может предложить!

Это было полезно?

Решение 2

Я полагал этого. Благодаря любому, кто ответил.

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

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

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

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

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

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

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

Другие советы

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

INTPTR [] Devnames = новый INTPTR [DeviceCount]; для (int i = 0; i <deviceCount; i ++) {devinames [i] = marshal.allochglobal [256]; }

Передайте этот массив HLP_GetDevicenames. Чтобы обрабатывать выходные данные, нанесите Marshal.PtrtoStringansi на каждый член Devs. Не забудьте выпустить Devnames [I] с маршалом. Брехглобаль в конце.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top