// wraps an existing native instance, with downcast support public static T WrapNative <T>(IntPtr native) where T : RefCounted { if (native == IntPtr.Zero) { return(null); } RefCounted r; WeakReference <RefCounted> w; // first see if we're already available if (nativeLookup.TryGetValue(native, out w)) { if (w.TryGetTarget(out r)) { // we're alive! return((T)r); } else { // we were seen before, but have since been GC'd, remove! nativeLookup.Remove(native); if (csb_Atomic_RefCounted_Refs(native) == 1) { // only managed ref remains, so release and return null csb_AtomicEngine_ReleaseRef(native); return(null); } csb_AtomicEngine_ReleaseRef(native); } } IntPtr classID = RefCounted.csb_Atomic_RefCounted_GetClassID(native); // and store, with downcast support for instance Component -> StaticModel // we never want to hit this path for script inherited natives NativeType nativeType; if (!nativeClassIDToNativeType.TryGetValue(classID, out nativeType)) { throw new System.InvalidOperationException("NativeCore.WrapNative - Attempting to wrap unknown native class id"); } r = nativeType.managedConstructor(native); w = new WeakReference <RefCounted>(r); NativeCore.nativeLookup[native] = w; // store a ref, so native side will not be released while we still have a reference in managed code r.AddRef(); return((T)r); }
// wraps an existing native instance, with downcast support public static T WrapNative <T> (IntPtr native) where T : RefCounted { if (native == IntPtr.Zero) { return(null); } // instance id uint id = csb_Atomic_RefCounted_GetRefID(native); WeakReference w; // first see if we're already available if (nativeLookup.TryGetValue(id, out w)) { if (w.IsAlive) { // we're alive! return((T)w.Target); } else { // we were seen before, but have since been GC'd, remove! nativeLookup.Remove(id); } } IntPtr classID = RefCounted.csb_Atomic_RefCounted_GetClassID(native); // and store, with downcast support for instance Component -> StaticModel // we never want to hit this path for script inherited natives RefCounted r = nativeClassIDToManagedConstructor[classID](native); w = new WeakReference(r); NativeCore.nativeLookup [id] = w; // store a ref, so native side will not be released while we still have a reference in managed code r.AddRef(); return((T)r); }