I know this question has already been asked and might be considered duplicate, but after reading other answers I am still quite baffled and do not understand explanation that is provided there.
I would be very grateful if someone could provided a sample code and some explanation.
I am working on following task:
I have a texture/textures (cannot be loaded from drive, generated on fly) in Unity and I convert it into an array. It can be an array of int, byte or float.
Currently, I do my object detection in C#, but I want to make it faster. Therefore, I want to do following.
Access a C++ code (from dll, I have just started my journey with c++) and run a method which would take my input array, do calculations and return a new array (old is not modified) to C# code.
Alternatively, I can input two arrays (preferred) where one of them is modified.
Output array does not have to be created every time, it can be overwritten.
I cannot use unsafe code in C# as this is for asset purposes (compatibility issues).
Mock-up code
C#
create arrays aOne,aTwo;
SomeC++Method(aOne,ref aTwo)
or
aTwo = SomeC++Method(aOne,aTwo)
or
aTwo = SomeC++Method(aOne) // variant where aTwo is created in C++
SomeC++MethodToDeAllocateMemory() //so there is no memory leak
C++
SomeC++Method(aOne,aTwo)
for (xyz)
do someting
return modified aTwo
SomeC++MethodToDeAllocateMemory()
release memory
I have found answer to this questions here: Updating a C# array inside C++ without Marshal.Copy or Unsafe
Sample solution:
c++ code:
extern "C" __declspec(dllexport) bool PopulateArray(float* floats, int length)
{
for (int i = 0; i < length; ++i)
{
floats[i] = i;
}
return true;
}
C# code
using UnityEngine;
using System.Runtime.InteropServices;
public class Test : MonoBehaviour {
[DllImport("ArrayFilling", CallingConvention = CallingConvention.Cdecl)]
public static extern bool PopulateArray([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] float[] floats, int length);
int length = 4000000; //corresponds to 2000x2000 texture of grayscale values
void Start()
{
//create new array
float[] floats = new float[length];
//used for speed test
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
//check internal method speed
sw.Start();
//floats array gets update here
Populate(ref floats);
sw.Stop();
Debug.Log("internal: " + sw.ElapsedMilliseconds);
sw.Reset();
//check external method speed
sw.Start();
//floats array gets updated here
PopulateArray(floats, length);
sw.Stop();
Debug.Log("external: " +sw.ElapsedMilliseconds);
}
void Populate(ref float[] floats)
{
for (int i = 0,n = length; i<n;i++)
{
floats[i] = i;
}
}
}
Regarding speed:
-external method (DLL) - 5 ms
-internal method (void Populate) - 23 ms