Ghopper21
Ghopper21

Reputation: 10477

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?

Upvotes: 6

Views: 12410

Answers (2)

Rodrigo Barros
Rodrigo Barros

Reputation: 39

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)

Upvotes: 3

Erwin
Erwin

Reputation: 188

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.

Upvotes: 7

Related Questions