The question is general but I am actually doing this with Mono and not .net, so if there are differences, I am very interested in what they are.
I have a simple data containing class (not struct for other reasons) which should be blitable in the sense that it consist of ints and doubles and smaller structs which consist of doubles. I am sending this to a native dll through DllImport static methods as a reference.
I was under the impression that for a simple object like that, what happens is that it is pinned in managed memory, the address of it, in managed memory, is passed to the native code as a reference/pointer (depending on how the native code is declared, same thing), the native code can read and write it, the function returns and the managed object is unpinned and may now hold changes written by the native code.
Others think the object is instead copied into a block of native memory and then the native code runs on it after which the data is copied back into the object in managed memory. This obviously being less performent and wasteful when the marshaling does not have to convert the data.
I made a test where I note the address of the data sent to native code and I see that it does not change per object. ObjectA gets one address, objectB gets another and each keep their address for as long as I tested.... but while that seems to support my understanding of this, there could still be other explanations for the addresses, so I would be grateful for a concrete explanation, since Mono documents do not mention pinning blittable objects while Microsoft documentation does.
Extra question: Can there can be a situation with a class (not struct) containing only ushort, int and double where it is not blittable but requires a copy? It was observed with mono on android that changes to the data in native code native would not be visible on managed side (when not using the Out decoration), seemingly indicating that copying, and not pinning, was used.
It is possible that the mono int may be different from the c++ int in the native code, but such data size and alignment issues should not be detectable from the managed side, so how would it "know" to marshal by copy and not pinning? In tests on windows such mismatch just result in garbled data, as expected, so that is likely not the reason for marshal by copy.