I am trying to communicate with an NFC reader/writer on a raspberry pi 3 using dotnet core.
I have to say that the different libnfc command line tools I used are all working fine (aka I can read and poll my tags, no problem on this side).
The idea is to use dotnet core and C# to orchestrate the libnfc library and it seems to work fine except as soon as the function I call returns a string, I get the following error message:
*** Error in `./NfcTest': free(): invalid pointer: 0x6d4ebc00 ***
NfcTest being the name of my app of course.
Here is the pinvoke definition
[DllImport("libnfc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string nfc_version();
Please note that after looking up on the web I did add the [return]
attribute myself but it did not change anything to the result. Same error is raised.
The code of the nfc_version in libnfc is here: https://github.com/nfc-tools/libnfc/blob/c3f739dea339a71c59d7d53ab6b0ecc477c3ab73/libnfc/nfc.c#L1325
It seems to return a "constant" and no do any freeing of any kind. So my guess would be that I misconfigured one of the attributes.
Another example is that I call the following:
[DllImport("libnfc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern string nfc_device_get_name(IntPtr pnd);
While I can perfectly call other methods (i.e. poll) using the pointer (pnd param) calling this one returns the same error as with the Version method. Both methods returning a string are making me wondering if the problem would not be in the DllImport but I'm not too sure how to fix that.
Link to lib code for that example: https://github.com/nfc-tools/libnfc/blob/c3f739dea339a71c59d7d53ab6b0ecc477c3ab73/libnfc/nfc.c#L1215
Any wisdom would be greatly appreciated.
The comment from Matthew Watson and the link he shared had the correct answer!
So I modified the pinvoke line like this:
[DllImport("libnfc", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr nfc_version();
Then I called it this way:
public string Version()
{
IntPtr ptr = Functions.nfc_version();
var str = Marshal.PtrToStringAuto(ptr);
return str;
}
And it works like a charm!
Thanks!