I'm working with an unmanaged C library which has a callback function that gets called from an internal thread in the C library. The callback has a void * 'context' parameter.
I want to set this context to the address of a C# class instance so that I can access member fields and properties from the callback.
My understanding is that I need to pin the memory of the class to ensure the GC does not move it since the C code will take a copy of address of the instance. However, GCHandle.Alloc() states that: "An instance with nonprimitive (non-blittable) members cannot be pinned."
And sure enough code attempting to pin a class or a struct containing a field of class type fails at runtime.
How can I pass the address of a C# class instance to my C++ code and ensure that the address remains valid (i.e. is not moved by GC)?
EDIT #1 Correction: the library is a C library, not C++ as previously stated (corrected in text above). Not that it should make any difference.
This the prototype for the C callback:
void Callback(uint32_t hCamera, uint32_t dwInterruptMask, void *pvParams);
And wrapped in C#:
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public unsafe delegate void PHX_AcquireCallBack(uint hCamera, uint dwInterruptMask,
IntPtr pvParams);
pvParams
is passed into the C library when the callback is installed. The library stores the pointer, but does not attempt to access it in any way. It just passes it back whenever it calls the callback.
When using the library from C++ code, I usually pass a this
pointer for pvParams
.