Beispiel #1
0
        internal static bool ToManagedValue(BorrowedReference value, Type obType,
                                            out object result, bool setError)
        {
            var usedImplicit = false;

            return(ToManagedValue(value.DangerousGetAddress(), obType, out result, setError, out usedImplicit));
        }
Beispiel #2
0
        public ExtensionType()
        {
            // Create a new PyObject whose type is a generated type that is
            // implemented by the particular concrete ExtensionType subclass.
            // The Python instance object is related to an instance of a
            // particular concrete subclass with a hidden CLR gchandle.

            BorrowedReference tp = TypeManager.GetTypeReference(GetType());

            //int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt);
            //if (rc > 1050)
            //{
            //    DebugUtil.Print("tp is: ", tp);
            //    DebugUtil.DumpType(tp);
            //}

            NewReference py = Runtime.PyType_GenericAlloc(tp, 0);

            // Borrowed reference. Valid as long as pyHandle is valid.
            tpHandle = tp.DangerousGetAddress();
            pyHandle = py.DangerousMoveToPointer();

#if DEBUG
            GetGCHandle(ObjectReference, TypeReference, out var existing);
            System.Diagnostics.Debug.Assert(existing == IntPtr.Zero);
#endif
            SetupGc();
        }
Beispiel #3
0
        internal unsafe static T *ReadPtr <T>(BorrowedReference ob, int offset)
            where T : unmanaged
        {
            Debug.Assert(offset >= 0);
            IntPtr ptr = Marshal.ReadIntPtr(ob.DangerousGetAddress(), offset);

            return((T *)ptr);
        }
Beispiel #4
0
        /// <summary>Creates a <see cref="NewReference"/> pointing to the same object</summary>
        public NewReference(BorrowedReference reference, bool canBeNull = false)
        {
            var address = canBeNull
                ? reference.DangerousGetAddressOrNull()
                : reference.DangerousGetAddress();

            Runtime.XIncref(address);
            this.pointer = address;
        }
Beispiel #5
0
        internal static void SetGCHandle(BorrowedReference reflectedClrObject, BorrowedReference type, GCHandle newHandle)
        {
            Debug.Assert(Runtime.PyObject_TypeCheck(reflectedClrObject, type));

            int offset = Marshal.ReadInt32(type.DangerousGetAddress(), Offsets.tp_clr_inst_offset);
            Debug.Assert(offset > 0);

            Marshal.WriteIntPtr(reflectedClrObject.DangerousGetAddress(), offset, (IntPtr)newHandle);
        }
Beispiel #6
0
        internal static void GetGCHandle(BorrowedReference reflectedClrObject, BorrowedReference type, out IntPtr handle)
        {
            Debug.Assert(reflectedClrObject != null);
            Debug.Assert(IsManagedType(type) || type == Runtime.CLRMetaType);
            Debug.Assert(Runtime.PyObject_TypeCheck(reflectedClrObject, type));

            int gcHandleOffset = Marshal.ReadInt32(type.DangerousGetAddress(), Offsets.tp_clr_inst_offset);
            Debug.Assert(gcHandleOffset > 0);

            handle = Marshal.ReadIntPtr(reflectedClrObject.DangerousGetAddress(), gcHandleOffset);
        }
Beispiel #7
0
        public NewReference(BorrowedReference reference, bool canBeNull = false)
        {
            var address = canBeNull
                ? reference.DangerousGetAddressOrNull()
                : reference.DangerousGetAddress();

#pragma warning disable CS0618 // Type or member is obsolete
            Runtime.XIncref(reference);
#pragma warning restore CS0618 // Type or member is obsolete
            this.pointer = address;
        }
Beispiel #8
0
        /// <summary>
        /// Creates new <see cref="PyObject"/> pointing to the same object as
        /// the <paramref name="reference"/>. Increments refcount, allowing <see cref="PyObject"/>
        /// to have ownership over its own reference.
        /// </summary>
        internal PyObject(BorrowedReference reference)
        {
            if (reference.IsNull)
            {
                throw new ArgumentNullException(nameof(reference));
            }

            obj = Runtime.SelfIncRef(reference.DangerousGetAddress());
#if TRACE_ALLOC
            Traceback = new StackTrace(1);
#endif
        }
Beispiel #9
0
        internal static void DumpInst(BorrowedReference ob)
        {
            BorrowedReference tp = Runtime.PyObject_TYPE(ob);
            nint sz = Util.ReadIntPtr(tp, TypeOffset.tp_basicsize);

            for (nint i = 0; i < sz; i += IntPtr.Size)
            {
                var    pp = new IntPtr(ob.DangerousGetAddress().ToInt64() + i);
                IntPtr v  = Marshal.ReadIntPtr(pp);
                Console.WriteLine("offset {0}: {1}", i, v);
            }

            Console.WriteLine("");
            Console.WriteLine("");
        }
Beispiel #10
0
        /// <summary>
        /// Creates a new managed type derived from a base type with any virtual
        /// methods overridden to call out to python if the associated python
        /// object has overridden the method.
        /// </summary>
        internal static Type CreateDerivedType(string name,
                                               Type baseType,
                                               BorrowedReference dictRef,
                                               string namespaceStr,
                                               string assemblyName,
                                               string moduleName = "Python.Runtime.Dynamic.dll")
        {
            // TODO: clean up
            IntPtr py_dict = dictRef.DangerousGetAddress();

            if (null != namespaceStr)
            {
                name = namespaceStr + "." + name;
            }

            if (null == assemblyName)
            {
                assemblyName = "Python.Runtime.Dynamic";
            }

            ModuleBuilder moduleBuilder = GetModuleBuilder(assemblyName, moduleName);

            Type baseClass  = baseType;
            var  interfaces = new List <Type> {
                typeof(IPythonDerivedType)
            };

            // if the base type is an interface then use System.Object as the base class
            // and add the base type to the list of interfaces this new class will implement.
            if (baseType.IsInterface)
            {
                interfaces.Add(baseType);
                baseClass = typeof(object);
            }

            TypeBuilder typeBuilder = moduleBuilder.DefineType(name,
                                                               TypeAttributes.Public | TypeAttributes.Class,
                                                               baseClass,
                                                               interfaces.ToArray());

            // add a field for storing the python object pointer
            // FIXME: fb not used
            FieldBuilder fb = typeBuilder.DefineField("__pyobj__", typeof(CLRObject), FieldAttributes.Public);

            // override any constructors
            ConstructorInfo[] constructors = baseClass.GetConstructors();
            foreach (ConstructorInfo ctor in constructors)
            {
                AddConstructor(ctor, baseType, typeBuilder);
            }

            // Override any properties explicitly overridden in python
            var pyProperties = new HashSet <string>();

            if (py_dict != IntPtr.Zero && Runtime.PyDict_Check(py_dict))
            {
                Runtime.XIncref(py_dict);
                using (var dict = new PyDict(py_dict))
                    using (PyObject keys = dict.Keys())
                    {
                        foreach (PyObject pyKey in keys)
                        {
                            using (PyObject value = dict[pyKey])
                            {
                                if (value.HasAttr("_clr_property_type_"))
                                {
                                    string propertyName = pyKey.ToString();
                                    pyProperties.Add(propertyName);

                                    // Add the property to the type
                                    AddPythonProperty(propertyName, value, typeBuilder);
                                }
                            }
                        }
                    }
            }

            // override any virtual methods not already overridden by the properties above
            MethodInfo[] methods        = baseType.GetMethods();
            var          virtualMethods = new HashSet <string>();

            foreach (MethodInfo method in methods)
            {
                if (!method.Attributes.HasFlag(MethodAttributes.Virtual) |
                    method.Attributes.HasFlag(MethodAttributes.Final))
                {
                    continue;
                }

                // skip if this property has already been overridden
                if ((method.Name.StartsWith("get_") || method.Name.StartsWith("set_")) &&
                    pyProperties.Contains(method.Name.Substring(4)))
                {
                    continue;
                }

                // keep track of the virtual methods redirected to the python instance
                virtualMethods.Add(method.Name);

                // override the virtual method to call out to the python method, if there is one.
                AddVirtualMethod(method, baseType, typeBuilder);
            }

            // Add any additional methods and properties explicitly exposed from Python.
            if (py_dict != IntPtr.Zero && Runtime.PyDict_Check(py_dict))
            {
                Runtime.XIncref(py_dict);
                using (var dict = new PyDict(py_dict))
                    using (PyObject keys = dict.Keys())
                    {
                        foreach (PyObject pyKey in keys)
                        {
                            using (PyObject value = dict[pyKey])
                            {
                                if (value.HasAttr("_clr_return_type_") && value.HasAttr("_clr_arg_types_"))
                                {
                                    string methodName = pyKey.ToString();

                                    // if this method has already been redirected to the python method skip it
                                    if (virtualMethods.Contains(methodName))
                                    {
                                        continue;
                                    }

                                    // Add the method to the type
                                    AddPythonMethod(methodName, value, typeBuilder);
                                }
                            }
                        }
                    }
            }

            // add the destructor so the python object created in the constructor gets destroyed
            MethodBuilder methodBuilder = typeBuilder.DefineMethod("Finalize",
                                                                   MethodAttributes.Family |
                                                                   MethodAttributes.Virtual |
                                                                   MethodAttributes.HideBySig,
                                                                   CallingConventions.Standard,
                                                                   typeof(void),
                                                                   Type.EmptyTypes);
            ILGenerator il = methodBuilder.GetILGenerator();

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("Finalize"));
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, baseClass.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance));
            il.Emit(OpCodes.Ret);

            Type type = typeBuilder.CreateType();

            // scan the assembly so the newly added class can be imported
            Assembly assembly = Assembly.GetAssembly(type);

            AssemblyManager.ScanAssembly(assembly);

            // FIXME: assemblyBuilder not used
            AssemblyBuilder assemblyBuilder = assemblyBuilders[assemblyName];

            return(type);
        }
Beispiel #11
0
 internal unsafe static IntPtr ReadIntPtr(BorrowedReference ob, int offset)
 {
     Debug.Assert(offset >= 0);
     return(Marshal.ReadIntPtr(ob.DangerousGetAddress(), offset));
 }
Beispiel #12
0
 internal static ManagedType GetManagedObject(BorrowedReference ob)
 => GetManagedObject(ob.DangerousGetAddress());
Beispiel #13
0
 internal CLRObject(object ob, BorrowedReference tp) : this(ob, tp.DangerousGetAddress())
 {
 }
Beispiel #14
0
 public static bool IsNone(this BorrowedReference reference)
 => reference.DangerousGetAddress() == Runtime.PyNone;
Beispiel #15
0
 private static bool ToPrimitive(BorrowedReference value, Type obType, out object?result, bool setError)
 => ToPrimitive(value.DangerousGetAddress(), obType, out result, setError);
Beispiel #16
0
 internal unsafe static void WriteIntPtr(BorrowedReference ob, int offset, IntPtr value)
 {
     Debug.Assert(offset >= 0);
     Marshal.WriteIntPtr(ob.DangerousGetAddress(), offset, value);
 }
Beispiel #17
0
 internal static bool IsManagedType(BorrowedReference type)
 {
     var flags = (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags);
     return (flags & TypeFlags.HasClrInstance) != 0;
 }
Beispiel #18
0
 internal static void WriteInt64(BorrowedReference ob, int offset, long value)
 {
     Debug.Assert(offset >= 0);
     Marshal.WriteInt64(ob.DangerousGetAddress(), offset, value);
 }
Beispiel #19
0
        internal static NewReference GetInstHandle(object ob, BorrowedReference pyType)
        {
            CLRObject co = GetInstance(ob, pyType.DangerousGetAddress());

            return(NewReference.DangerousFromPointer(co.pyHandle));
        }
Beispiel #20
0
 internal static bool ToManagedValue(BorrowedReference value, Type obType,
                                     out object result, bool setError)
 => ToManagedValue(value.DangerousGetAddress(), obType, out result, setError);
Beispiel #21
0
 internal static long ReadInt64(BorrowedReference ob, int offset)
 {
     Debug.Assert(offset >= 0);
     return(Marshal.ReadInt64(ob.DangerousGetAddress(), offset));
 }
 internal static bool TryDecode(BorrowedReference value, BorrowedReference type, Type targetType, out object result)
 => TryDecode(value.DangerousGetAddress(), type.DangerousGetAddress(), targetType, out result);
Beispiel #23
0
        /// <summary>
        /// The actual import hook that ties Python to the managed world.
        /// </summary>
        public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
        {
            var args = new BorrowedReference(argsRaw);

            // Replacement for the builtin __import__. The original import
            // hook is saved as this.py_import. This version handles CLR
            // import and defers to the normal builtin for everything else.

            var num_args = Runtime.PyTuple_Size(args);

            if (num_args < 1)
            {
                return(Exceptions.RaiseTypeError("__import__() takes at least 1 argument (0 given)"));
            }

            BorrowedReference py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if (py_mod_name.IsNull ||
                !Runtime.IsStringType(py_mod_name))
            {
                return(Exceptions.RaiseTypeError("string expected"));
            }

            // Check whether the import is of the form 'from x import y'.
            // This determines whether we return the head or tail module.

            BorrowedReference fromList = default;
            var fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if (fromList != null &&
                    Runtime.PyObject_IsTrue(fromList) == 1)
                {
                    fromlist = true;
                }
            }

            string mod_name = Runtime.GetManagedString(py_mod_name);

            // Check these BEFORE the built-in import runs; may as well
            // do the Incref()ed return here, since we've already found
            // the module.
            if (mod_name == "clr")
            {
                NewReference clr_module = GetCLRModule(fromList);
                if (!clr_module.IsNull())
                {
                    BorrowedReference sys_modules = Runtime.PyImport_GetModuleDict();
                    if (!sys_modules.IsNull)
                    {
                        Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module);
                    }
                }
                return(clr_module.DangerousMoveToPointerOrNull());
            }

            string realname = mod_name;

            // 2010-08-15: Always seemed smart to let python try first...
            // This shaves off a few tenths of a second on test_module.py
            // and works around a quirk where 'sys' is found by the
            // LoadImplicit() deprecation logic.
            // Turns out that the AssemblyManager.ResolveHandler() checks to see if any
            // Assembly's FullName.ToLower().StartsWith(name.ToLower()), which makes very
            // little sense to me.
            IntPtr res = Runtime.PyObject_Call(py_import, args.DangerousGetAddress(), kw);

            if (res != IntPtr.Zero)
            {
                // There was no error.
                if (fromlist && IsLoadAll(fromList))
                {
                    var mod = ManagedType.GetManagedObject(res) as ModuleObject;
                    mod?.LoadNames();
                }
                return(res);
            }
            // There was an error
            if (!Exceptions.ExceptionMatches(Exceptions.ImportError))
            {
                // and it was NOT an ImportError; bail out here.
                return(IntPtr.Zero);
            }

            if (mod_name == string.Empty)
            {
                // Most likely a missing relative import.
                // For example site-packages\bs4\builder\__init__.py uses it to check if a package exists:
                //     from . import _html5lib
                // We don't support them anyway
                return(IntPtr.Zero);
            }
            // Save the exception
            var originalException = new PythonException();

            // Otherwise,  just clear the it.
            Exceptions.Clear();

            string[] names = realname.Split('.');

            // See if sys.modules for this interpreter already has the
            // requested module. If so, just return the existing module.
            BorrowedReference modules = Runtime.PyImport_GetModuleDict();
            BorrowedReference module  = Runtime.PyDict_GetItem(modules, py_mod_name);

            if (module != null)
            {
                if (fromlist)
                {
                    if (IsLoadAll(fromList))
                    {
                        var mod = ManagedType.GetManagedObject(module) as ModuleObject;
                        mod?.LoadNames();
                    }
                    return(new NewReference(module).DangerousMoveToPointer());
                }

                module = Runtime.PyDict_GetItemString(modules, names[0]);
                return(new NewReference(module, canBeNull: true).DangerousMoveToPointer());
            }
            Exceptions.Clear();

            // Traverse the qualified module name to get the named module
            // and place references in sys.modules as we go. Note that if
            // we are running in interactive mode we pre-load the names in
            // each module, which is often useful for introspection. If we
            // are not interactive, we stick to just-in-time creation of
            // objects at lookup time, which is much more efficient.
            // NEW: The clr got a new module variable preload. You can
            // enable preloading in a non-interactive python processing by
            // setting clr.preload = True

            ModuleObject head = mod_name == realname ? null : root;
            ModuleObject tail = root;

            root.InitializePreload();

            foreach (string name in names)
            {
                ManagedType mt = tail.GetAttribute(name, true);
                if (!(mt is ModuleObject))
                {
                    originalException.Restore();
                    return(IntPtr.Zero);
                }
                if (head == null)
                {
                    head = (ModuleObject)mt;
                }
                tail = (ModuleObject)mt;
                if (CLRModule.preload)
                {
                    tail.LoadNames();
                }

                // Add the module to sys.modules
                Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.ObjectReference);
            }

            {
                var mod = fromlist ? tail : head;

                if (fromlist && IsLoadAll(fromList))
                {
                    mod.LoadNames();
                }

                Runtime.XIncref(mod.pyHandle);
                return(mod.pyHandle);
            }
        }
Beispiel #24
0
 /// <summary>Create a scope based on a Python Module.</summary>
 internal PyScope(BorrowedReference reference, PyScopeManager manager)
     : this(reference.DangerousGetAddress(), manager)
 {
     Runtime.XIncref(reference.DangerousGetAddress());
 }