public static IntPtr RegisterNative(IntPtr native, RefCounted r) { r.nativeInstance = native; var w = new WeakReference(r); NativeCore.nativeLookup [r.RefID] = w; r.AddRef(); return(native); }
// register a newly created native public static IntPtr RegisterNative(IntPtr native, RefCounted r) { r.nativeInstance = native; var w = new WeakReference(r); NativeCore.nativeLookup [native] = w; // keep native side alive r.AddRef(); return(native); }
// 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_Clockwork_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_Clockwork_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); }