3

I have to pass an Byte array containing an MAC-Address to a C++ Method. Since I don't have much experience with working with c C++ APIsI don't know how to do this. I've tried to pass the array itself, but got an invalid parameter code as response from the API. I've also tried to create an IntPtr but to no avail.
I know that the problem is that C++ can't handle managed datatypes such as arrays, so I've to create a unmanaged array somehow, I think.

Here is the definition of the C++ Method:

ll_status_t LL_Connect(
ll_intf_t intf, 
uint8_t address[6]);

The array in C# is defined the following way:

Byte[] addr = new Byte[6];

Of course, the array is not empty.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
  • byte[] in C# to unsigned char* in C++ is what I use to do this – jjmcc Apr 03 '18 at 17:57
  • You have to create an unmanaged array, C#'s arrays are not the same as C++'s. – Hatted Rooster Apr 03 '18 at 17:57
  • Thanks, but i can't change anything in the c++ part. @SombreroChicken, i know that, i don't know how to create an unmanaged array. – Simon SCHÖNEGGER Apr 03 '18 at 18:08
  • Using byte[] in the C# code is the correct way. Getting the [DllImport] declaration wrong is the standard explanation. We can't see it. https://stackoverflow.com/questions/15660722/why-are-cdecl-calls-often-mismatched-in-the-standard-p-invoke-convention/15664100#15664100 – Hans Passant Apr 03 '18 at 18:27
  • I would look into where exactly the "invalid parameter code" error is coming from. Is it coming from the C# code trying to call the C++ code or from the C++ code itself. Maybe you are passing parameters fine but the code just doesn't like the parameters you are passing. Also is it possible to debug the C++ code at all and see what parameters it's receiving? – Wearwolf Apr 03 '18 at 21:28

1 Answers1

4

For example:

C++

extern "C"
{
    __declspec(dllexport) void GetData(uint8_t* data, uint32_t length)
    {
      for (size_t i = 0; i < length; ++i)
        data[i] = i;
    }
}

C#

[DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetData([In, Out] [MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length);

And use in C#

 byte[] data = new byte[4];
 GetData(data, (unit)data.Lenght);

If you have an array fixed length, for example:

C++

extern "C"
{
    __declspec(dllexport) void GetData(uint8_t data[6])
    {
      for (size_t i = 0; i < 6; ++i)
        data[i] = i;
    }
}

C#

[DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetData([In, Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] data);

And use in C#

 byte[] data = new byte[6];
 GetData(data);

For your case:

    [DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int LL_Connect(byte intf, [In, Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] address);
Neargye
  • 1,870
  • 1
  • 12
  • 12
  • thanks for your answer! unfortunally i can't change any of the existing c++ code. As stated above the method to be called is defined in the following way: `ll_status_t LL_Connect( ll_intf_t intf, uint8_t address[6]);` ll_intf_t is just a Byte... so i have to pass my array somehow. – Simon SCHÖNEGGER Apr 03 '18 at 18:46
  • For this case use: [DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern int LL_Connect(byte intf, [In, Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] address); See my edit commet. – Neargye Apr 03 '18 at 18:59
  • Thank you very much!!! Seems like a great approach! Still getting the invalid parameter response, but I'm going to look into that tomorrow. **thank you very much!!** – Simon SCHÖNEGGER Apr 03 '18 at 19:36