// Called just after invoking the COM method. The IntPtr is the same one that just got returned // from MarshalManagedToNative. The return value is unused. public object MarshalNativeToManaged(IntPtr pNativeData) { // When we are called with pNativeData == m_ArrayPtr, do nothing. All the // work is done when: if(pNativeData == m_MFIntPtr) { // Read the count int count = Marshal.ReadInt32(pNativeData); // If we have an array to return things in (ie MFTGetInfo wasn't passed // nulls) if(m_array != null) { IntPtr ip2 = Marshal.ReadIntPtr(m_ArrayPtr); // I don't know why this might happen, but it seems worth the check if(ip2 != IntPtr.Zero) { try { int iSize = Marshal.SizeOf(typeof(MFTRegisterTypeInfo)); // Size the array m_array.Capacity = count; // Copy in the values for(int x = 0; x < count; x++) { var rti = new MFTRegisterTypeInfo(); Marshal.PtrToStructure(new IntPtr(ip2.ToInt64() + (x*iSize)), rti); m_array.Add(rti); } } finally { // Free the array we got back Marshal.FreeCoTaskMem(ip2); } } } // Don't forget to assign the value m_int.Assign(count); m_int = null; m_array = null; } // This value isn't actually used return null; }
public IntPtr MarshalManagedToNative(object managedObj) { IntPtr p; // We get called twice: Once for the MFInt, and once for the array. // Figure out which call this is. if(managedObj is MFInt) { // Save off the object. We'll need to use Assign() on this later. m_int = managedObj as MFInt; // Allocate room for the int p = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(MFInt))); m_MFIntPtr = p; } else { // Save off the object. We'll be calling methods on this in // MarshalNativeToManaged. m_array = managedObj as ArrayList; if(m_array != null) { m_array.Clear(); } // All we need is room for the pointer p = Marshal.AllocCoTaskMem(IntPtr.Size); // Belt-and-suspenders. Set this to null. Marshal.WriteIntPtr(p, IntPtr.Zero); m_ArrayPtr = p; } return p; }