示例#1
0
        // 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 (csi_Atomic_RefCounted_Refs(native) == 1)
                    {
                        // only managed ref remains, so release and return null
                        csi_AtomicEngine_ReleaseRef(native);
                        return(null);
                    }

                    csi_AtomicEngine_ReleaseRef(native);
                }
            }

            IntPtr classID = RefCounted.csi_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 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);
        }
示例#2
0
        // wraps an existing native instance, with downcast support
        public static T WrapNative <T>(IntPtr native) where T : RefCounted
        {
            if (native == IntPtr.Zero)
            {
                throw new InvalidOperationException("NativeCore.WrapNative - Attempting to wrap native instance IntPtr.Zero");
            }

            var reference = refCountedCache.Get(native)?.Reference;

            // This isn't really a good test to verify right object, better to test if not a T and error?
            if (reference is T)
            {
                return((T)reference);
            }

            IntPtr classID = RefCounted.csi_Atomic_RefCounted_GetClassID(native);

            // Check whether this is a valid native class to wrap
            NativeType nativeType;

            if (!nativeClassIDToNativeType.TryGetValue(classID, out nativeType))
            {
                if (logWrapUnknownNative)
                {
                    Log.Info("WrapNative returning null for unknown class: " + GetNativeTypeName(native));
                }

                return(null);
            }

            // TODO: make CSComponent abstract and have general abstract logic here?
            if (nativeType.Type == typeof(CSComponent))
            {
                return(null);
            }

            // Construct managed instance wrapper for native instance
            // this has downcast support for instance Component -> StaticModel
            // note, we never want to hit this path for script inherited natives

            var r = nativeType.managedConstructor(native);

            // IMPORTANT: if a RefCounted instance is created in managed code, has reference count increased in native code
            // and managed side is GC'd, the original NET created instance will be gone and we can get it back here reported
            // as instantiated in native code.  May want a transative boolean to be able to tell when an object has passed this "barrier"
            // which is somewhat common
            RegisterNative(native, r, InstantiationType.INSTANTIATION_NATIVE);

            return((T)r);
        }
示例#3
0
        // 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 (csi_Atomic_RefCounted_Refs(native) == 1)
                    {
                        // only managed ref remains, so release and return null
                        csi_AtomicEngine_ReleaseRef(native);
                        return(null);
                    }

                    csi_AtomicEngine_ReleaseRef(native);
                }
            }

            IntPtr classID = RefCounted.csi_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 InvalidOperationException("NativeCore.WrapNative - Attempting to wrap unknown native class id");
            }

            // TODO: make CSComponent abstract and have general abstract logic here?
            if (nativeType.Type == typeof(CSComponent))
            {
                return(null);
            }

            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();

            // Note: r.InstantiationType may be INSTANTIATION_NET here is we were GC'd, native still had a reference, and we came back
            if (r.InstantiationType == InstantiationType.INSTANTIATION_NET)
            {
                //Log.Warn($"Wrapped {r.GetType().Name} was originally instantiated in NET, changing to native, this is likely an error");
                //r.InstantiationType = InstantiationType.INSTANTIATION_NATIVE;
            }

            r.PostNativeUpdate();

            return((T)r);
        }