/// <summary> /// Gets the GluonObject representation of the underlying pointer. /// If GluonObject already existed, /// calls Marshal.Release() on the native pointer before returning the existing object. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="native"></param> /// <returns></returns> public static T Of <T>(IntPtr native) where T : GluonObject { if (native == IntPtr.Zero) { return(null); } lock (All) { WeakReference rret; GluonObject ret; if (All.TryGetValue(native, out rret) || All.TryGetValue(GetRootPointer(native), out rret)) { ret = rret.Target as GluonObject; Marshal.Release(native); } else { var id = VTObject.Id; IntPtr ioPtr; Marshal.QueryInterface(native, ref id, out ioPtr); if (ioPtr == IntPtr.Zero) { return(null); } VTObject io = VTUnknown.GetVTable <VTObject>(ioPtr); io.GetTypeId(ioPtr, ref id); Marshal.Release(ioPtr); Func <IntPtr, GluonObject> factory; if (!WrapperFactories.TryGetValue(id, out factory)) { return(null); } ret = factory(ioPtr); if (ret == null) { throw new Exception("Failed to construct wrapper for native type " + native.GetType().ToString()); } } return(ret as T); } }
private static IntPtr GetRootPointer(IntPtr native) { var id = VTObject.Id; IntPtr ptr; Marshal.QueryInterface(native, ref id, out ptr); if (ptr == IntPtr.Zero) { return(IntPtr.Zero); } Marshal.Release(ptr); VTObject io = VTUnknown.GetVTable <VTObject>(ptr); io.GetTypeId(ptr, ref id); return(io.CastTo(ptr, ref id)); }