ข้อยกเว้นตัวชี้ไม่ถูกต้องโดยใช้ pinvoid บน libnfc สำหรับค่าสตริง [ซ้ำกัน]

ฉันกำลังพยายามสื่อสารกับเครื่องอ่าน/เขียน NFC บน Raspberry Pi 3 โดยใช้ dotnet core

ฉันต้องบอกว่าเครื่องมือบรรทัดคำสั่ง libnfc ต่างๆ ที่ฉันใช้ทำงานได้ดี (หรือที่รู้จักว่าฉันสามารถอ่านและสำรวจแท็กของฉันได้ ไม่มีปัญหาในด้านนี้)

แนวคิดคือการใช้ dotnet core และ C# เพื่อประสานไลบรารี libnfc และดูเหมือนว่าจะทำงานได้ดี ยกเว้นทันทีที่ฟังก์ชันที่ฉันเรียกใช้ส่งคืนสตริง ฉันได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้:

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

แน่นอนว่า NfcTest เป็นชื่อแอปของฉัน

นี่คือคำจำกัดความของพินโวค

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

โปรดทราบว่าหลังจากค้นหาเว็บแล้ว ฉันได้เพิ่มแอตทริบิวต์ [return] ด้วยตัวเอง แต่ผลลัพธ์ไม่ได้เปลี่ยนแปลงอะไรเลย เกิดข้อผิดพลาดเดียวกัน

รหัสของ nfc_version ใน libnfc อยู่ที่นี่: https://github.com/nfc-tools/libnfc/blob/c3f739dea339a71c59d7d53ab6b0ecc477c3ab73/libnfc/nfc.c#L1325

ดูเหมือนว่าจะกลับมาคงที่และไม่มีการปล่อยใดๆ ทั้งสิ้น ดังนั้นฉันเดาว่าฉันกำหนดค่าแอตทริบิวต์ตัวใดตัวหนึ่งไม่ถูกต้อง

อีกตัวอย่างหนึ่งคือฉันเรียกสิ่งต่อไปนี้:

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

ในขณะที่ฉันสามารถเรียกวิธีอื่นได้อย่างสมบูรณ์แบบ (เช่นการสำรวจความคิดเห็น) โดยใช้ตัวชี้ (pnd พารามิเตอร์) การเรียกวิธีนี้จะส่งคืนข้อผิดพลาดเดียวกันกับวิธี Version ทั้งสองวิธีส่งคืนสตริงทำให้ฉันสงสัยว่าปัญหาจะไม่อยู่ใน DllImport หรือไม่ แต่ฉันก็ไม่แน่ใจเหมือนกันว่าจะแก้ไขได้อย่างไร

ลิงก์ไปยังโค้ด lib สำหรับตัวอย่างนั้น: https://github.com/nfc-tools/libnfc/blob/c3f739dea339a71c59d7d53ab6b0ecc477c3ab73/libnfc/nfc.c#L1215

ภูมิปัญญาใด ๆ จะได้รับการชื่นชมอย่างมาก


person Georges Legros    schedule 23.02.2021    source แหล่งที่มา
comment
อ่านสิ่งนี้ เป็นไปได้ว่าคุณจะต้องส่งคืน IntPtr และนำสิ่งนั้นกลับมาที่สตริงด้วยตัวเอง   -  person Matthew Watson    schedule 23.02.2021


คำตอบ (1)


ความคิดเห็นจาก Matthew Watson และลิงก์ที่เขาแชร์มีคำตอบที่ถูกต้อง!

ดังนั้นฉันจึงแก้ไขบรรทัดพินโวคดังนี้:

[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