I don’t want to share an array between jslib and Unity. What I want is to create an array in the js side and pass it as an argument from a function in Unity. I know how to do it with single values like string, int, float, using cwrap on the js side and MonoPInvokeCallback on the Unity side. But not arrays.
I tried following this, my c# function is a simple
The code examples look great. If you intend for the arrays to be immediately consumed and not retained, you can defer the freeing in case 1 and 3 via
setTimeout(function() { _free(ptr); }, 0);
That way the allocated blocks will be freed up after the current rendered frame finishes. Of course this does have the issue that if you do a lot of repeated calls to a JS function within the same frame, the allocs would pile up and temporarily consume more memory than needed. In that case, it may make sense to pool the allocated ptrs for reuse within a frame.
The reason why it wasn’t working is because I can’t pass the array of doubles directly, I need to use the IntPtr and Marshal like you did @gtk2k . Thanks!
@jukka_j Just curious, should I use Marshal.Copy or NativeArray.CopyTo or something else? I want the fastest way available. In other places I found that Marshal.Copy is the best way to go, but I want to confirm in the current state of Unity what is the best thing to use. Thanks!
Also I was trying to marshal to a object using
[StructLayout(LayoutKind.Sequential)]
public class cantmarshalwhy{
public (double a, double b , double c) whycantmarshaldis;
}
Marshal.PtrToStructure<cantmarshalwhy>(ptr, cantmarshalwhy_instance);
But I keep getting an error saying I can’t marshal the field “whycantmarshaldis”. Are tuples not supported? I searched but couldn’t find anything. Using Marshal.Copy works but would be nice if I could marshal to an instance of a class with tuples.
EDIT
Yea the problem are tuples. If I use structs instead it works.
Both Marshal.Copy and NativeArray.CopyTo should yield the same result in this case. Not sure about the rationale behind tuples - maybe C# does not define a memory layout for tuples the way it does for structs, or maybe there is something IL2CPP does not implement there. Definitely recommend using structs.
@jukka_j@gtk2k
one last question. Why do you need to do “buf >> 3” on “Module.HEAPF64.set(data), buf >> 3)”? I know you are dividing by 8, but why do you need to do this? Why can’t the offset be 0? I thought the malloc operation already returned the offset to the initial position of the array. I tried searching this but couldn’t find anything.
JavaScript typed arrays access elements as if they are logical arrays containing aligned elements of the appropriate type, and not via absolute byte addresses. See the diagram at JavaScript typed arrays - JavaScript | MDN for an illustration.
So HEAPF64[0] accesses the first double (at byte address 0), HEAPF64[1] accesses the second double (at byte address 8) and so on.
This can cause memory access out of bounds. Don’t do it. It was hard to debug, but this is the cause. Free the memory in the C# side. For whatever reason, deferred freeing can randomly fail.