I would like to pin an array of .NET objects (including the objects) in order to allow a native function to do some processing on the objects. As far as I understood, GCHandle.Alloc() does not allow me to do this, because such an array contains references (and the objects might also contain references) which are not blittable.
Is there any other option to achieve this? I would be okay with very hack-y suggestions or ones that require Mono.
You could take a look at
Marshal.AllocHGlobal
andMarshal.WriteIntPtr
. This is the official way that framework provides to work with unmanaged memory. Not sure if it will be helpful though.Edit
See also https://stackoverflow.com/a/878147/301525
Arrays in .NET are represented in contiguous memory. So that means that in memory, after element 0, element 1 will come directly after the previous element, and so on.
If you pin the array with
GCHandle.Alloc
, then that means the entire list of elements is pinned in memory as well, and you can process that in unmanaged code.However, as you've mentioned, it only makes sense if the type is a blittable type (technically, this is not true, it's if the type is able to be marshaled to unmanaged code, although there's a lot of overlap here between the blittable primary types and stuff that the P/Invoke/COM Interop layers handle automatically).
So if you have an array of value types, you can call
GCHandle.Alloc
and it will pin the array for you. However, the P/Invoke layer already does this for you, so you shouldn't be concerned with this.If your array is full of references, then marshalling it to unamanged code doesn't make sense anyways; even if you pin every reference, the unmanaged code wouldn't know what to do with that reference in memory, as the type system doesn't support the .NET type that the reference is pointing to in memory.
If the class in .NET is really a wrapper/.NET representation of a native structure, then you're better off creating an array of that structure in .NET, copying all the data into it, and then sending it to your native code.
Or, you could write your class in C++/cli to facilitate the access of the .NET members in native code.