Passing a byte array from Unity C# into a C++ library method

10,203

Solution 1

You have to change your method definition to take an IntPtr. This is the C# way to define a pointer to non-managed memory. To create this pointer use Marshal.AllocHGlobal() and then copy the data to it using Marshal.Copy().

Example (not tested):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Assets.Scripts
{
    public class DLLCall
    {

        [DllImport("thedll")]
        public static extern void TheCall(IntPtr byteArray, int size);

        public void PerformCall(byte[] data)
        {
            IntPtr unmanagedArray = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, unmanagedArray, data.Length);

            TheCall(unmanagedArray, data.Length);

            Marshal.FreeHGlobal(unmanagedArray);
        }

    }
}

Notice that you have to free the unmanaged memory manually by using Marshal.FreeHGlobal. After this the memory is no longer valid so the C++ library can't use it any more. If it needs to access the array at a later point remove the FreeHGlobal call and make sure to delete the memory after the library no longer requires access to it.

Solution 2

works for me:

in unity:

[DllImport ("dllplugin")]
public static extern void Method (byte[] bytes);

in c++ Plugin

#define EXPORT_API __declspec(dllexport)

extern "C" void EXPORT_API Method(unsigned char* bytes)
Share:
10,203
Ghopper21
Author by

Ghopper21

Slowing converting from Stack Overflow lurker into a contributing member. SOreadytohelp

Updated on June 05, 2022

Comments

  • Ghopper21
    Ghopper21 almost 2 years

    I have a C++ library method that I'd like to call from a Unity C# script.

    I understand there are three key steps. First, to declare the C++ methods to be extern "C". Second, to use [DllImport('foobar')] before the corresponding C# extern method declaration. Third, to name the library file with the lib prefix (e.g. libfoobar.so) and place it in the Unity plugins folder.

    So far so good -- if I'm only passing simple parameter types like int from C# into C++. However, to pass a byte[] parameter, I will need to account for the different ways C# and C++ handle memory and pointers. I haven't been able to find a definitive example of how to this should be done.

    My question: how to pass a byte[] from a Unity C# script into a external C++ library method?

  • Rajesh
    Rajesh over 6 years
    I am passing the byte array from unity to c++ plugin like this way, It works fine but untiy sending the 17 bytes otherside(C++) receive 4 bytes only.what is the reason?Please Help
  • Admin
    Admin over 4 years
    @Rajesh Same problem here. Passing 4096 bytes from C# to C++, but on the C++ end the array is only ever 8 bytes according to sizeof(bytes).
  • Admin
    Admin over 4 years
    Additionally, changing it to a unsigned char* rather than a char just makes sizeof 8 while the length of the array is 1.
  • Pierre Wargnier
    Pierre Wargnier over 4 years
    I know this is an old post but in C++, sizeof(bytes) will only give you the size of the pointer and not the size of the data it points to, see the first answer on this post : stackoverflow.com/questions/399003/… . If you want to do it this way, you will need to also pass the length of the C# bytes array.
  • Pierre Wargnier
    Pierre Wargnier over 4 years
    I edited the answer for the function to also have the length of the array as parameter. Note that in this case, we do not need element size since we know it is one byte per element. On the c++ side, the start of the buffer will be bytes and the end of the buffer will be bytes + length.