-1

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.

Georges Legros
  • 2,494
  • 2
  • 23
  • 42
  • 2
    Have a read of [this](https://stackoverflow.com/questions/370079/pinvoke-for-c-function-that-returns-char). It's likely that you will need to return an `IntPtr` and marshal that to a string yourself. – Matthew Watson Feb 23 '21 at 09:15

1 Answers1

1

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!

Georges Legros
  • 2,494
  • 2
  • 23
  • 42