Исключение недопустимого указателя с использованием pinvoke в libnfc для строковых значений

Я пытаюсь связаться с устройством чтения / записи NFC на raspberry pi 3, используя ядро ​​dotnet.

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

Идея состоит в том, чтобы использовать ядро ​​dotnet и C # для оркестровки библиотеки libnfc, и, похоже, она работает нормально, за исключением случаев, когда вызываемая мной функция возвращает строку, я получаю следующее сообщение об ошибке:

*** Error in `./NfcTest': free(): invalid pointer: 0x6d4ebc00 ***

NfcTest - это, конечно, название моего приложения.

Вот определение pinvoke

[DllImport("libnfc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string nfc_version();

Обратите внимание, что после поиска в Интернете я сам добавил атрибут [return], но это ничего не изменило в результате. Возникает такая же ошибка.

Код версии nfc_version в libnfc находится здесь:

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

Другой пример: я называю следующее:

[DllImport("libnfc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern string nfc_device_get_name(IntPtr pnd);

Хотя я могу отлично вызывать другие методы (например, опрос) с помощью указателя (параметр pnd), вызов этого метода возвращает ту же ошибку, что и метод версии. Оба метода, возвращающие строку, заставляют меня задуматься, не будет ли проблема в DllImport, но я не слишком уверен, как это исправить.

Ссылка на код библиотеки для этого примера:

Любая мудрость будет принята с благодарностью.


person Georges Legros    schedule 23.02.2021    source источник
comment
Прочтите это. Скорее всего, вам нужно будет вернуть IntPtr и выполнить маршалинг его в строку самостоятельно.   -  person Matthew Watson    schedule 23.02.2021


Ответы (1)


Комментарий Мэтью Уотсона и ссылка, которой он поделился, содержали правильный ответ!

Итак, я изменил строку pinvoke следующим образом:

[DllImport("libnfc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr nfc_version();

Тогда я назвал это так:

public string Version()
{
    IntPtr ptr = Functions.nfc_version();
    var str = Marshal.PtrToStringAuto(ptr);
    return str;   
}

И это работает как шарм!

Спасибо!

person Georges Legros    schedule 23.02.2021