Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 623
Ghopper21 Avatar asked Mar 20 '15 16:03

Ghopper21


2 Answers

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.

like image 72
Erwin Avatar answered Oct 17 '22 19:10

Erwin


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)
like image 3
Rodrigo Barros Avatar answered Oct 17 '22 19:10

Rodrigo Barros