GetManagedObject() static private method

static private GetManagedObject ( IntPtr ob ) : ManagedType
ob System.IntPtr
return ManagedType
コード例 #1
0
        public new static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val)
        {
            var managedKey = Runtime.GetManagedString(key);

            if ((settableAttributes.Contains(managedKey)) ||
                (ManagedType.GetManagedObject(val)?.GetType() == typeof(ModuleObject)))
            {
                var self = (ModuleObject)ManagedType.GetManagedObject(ob);
                return(Runtime.PyDict_SetItem(self.dict, key, val));
            }

            return(ExtensionType.tp_setattro(ob, key, val));
        }
コード例 #2
0
        internal static void RestoreRuntimeData(ImportHookState storage)
        {
            py_clr_module = storage.PyCLRModule;
            var rootHandle = storage.Root;

            root      = new PyObject(rootHandle);
            clrModule = (CLRModule)ManagedType.GetManagedObject(rootHandle) !;
            BorrowedReference dict = Runtime.PyImport_GetModuleDict();

            Runtime.PyDict_SetItemString(dict, "clr", ClrModuleReference);
            SetupNamespaceTracking();

            RestoreDotNetModules(storage.Modules);
        }
コード例 #3
0
        //====================================================================
        // Register a new Python object event handler with the event.
        //====================================================================

        internal bool AddEventHandler(IntPtr target, IntPtr handler)
        {
            Object obj = null;

            if (target != IntPtr.Zero)
            {
                CLRObject co = (CLRObject)ManagedType.GetManagedObject(target);
                obj = co.inst;
            }

            // Create a true delegate instance of the appropriate type to
            // wrap the Python handler. Note that wrapper delegate creation
            // always succeeds, though calling the wrapper may fail.

            Type     type = this.info.EventHandlerType;
            Delegate d    = PythonEngine.DelegateManager.GetDelegate(type, handler);

            // Now register the handler in a mapping from instance to pairs
            // of (handler hash, delegate) so we can lookup to remove later.
            // All this is done lazily to avoid overhead until an event is
            // actually subscribed to by a Python event handler.

            if (reg == null)
            {
                reg = new Hashtable();
            }
            object    key  = (obj != null) ? obj : this.info.ReflectedType;
            ArrayList list = reg[key] as ArrayList;

            if (list == null)
            {
                list     = new ArrayList();
                reg[key] = list;
            }
            list.Add(new Handler(Runtime.PyObject_Hash(handler), d));

            // Note that AddEventHandler helper only works for public events,
            // so we have to get the underlying add method explicitly.

            object[]   args = { d };
            MethodInfo mi   = this.info.GetAddMethod(true);

            mi.Invoke(obj, BindingFlags.Default, null, args, null);

            return(true);
        }
コード例 #4
0
        private static int TraverseTypeClear(IntPtr ob, IntPtr arg)
        {
            var visited = (HashSet <IntPtr>)GCHandle.FromIntPtr(arg).Target;

            if (!visited.Add(ob))
            {
                return(0);
            }
            var clrObj = ManagedType.GetManagedObject(ob);

            if (clrObj != null)
            {
                clrObj.CallTypeTraverse(TraverseTypeClear, arg);
                clrObj.CallTypeClear();
            }
            return(0);
        }
コード例 #5
0
        //====================================================================
        // Implements __contains__ for array types.
        //====================================================================

        public static int sq_contains(IntPtr ob, IntPtr v)
        {
            CLRObject obj      = (CLRObject)ManagedType.GetManagedObject(ob);
            Type      itemType = obj.inst.GetType().GetElementType();
            IList     items    = obj.inst as IList;
            object    value;

            if (!Converter.ToManaged(v, itemType, out value, false))
            {
                return(0);
            }

            if (items.Contains(value))
            {
                return(1);
            }

            return(0);
        }
コード例 #6
0
        private static Exception FromPyErr(BorrowedReference typeRef, BorrowedReference valRef, BorrowedReference tbRef,
                                           out ExceptionDispatchInfo?exceptionDispatchInfo)
        {
            if (valRef == null)
            {
                throw new ArgumentNullException(nameof(valRef));
            }

            var type      = PyType.FromReference(typeRef);
            var value     = new PyObject(valRef);
            var traceback = PyObject.FromNullableReference(tbRef);

            exceptionDispatchInfo = TryGetDispatchInfo(valRef);
            if (exceptionDispatchInfo != null)
            {
                return(exceptionDispatchInfo.SourceException);
            }

            if (ManagedType.GetManagedObject(valRef) is CLRObject {
                inst : Exception e
            })
コード例 #7
0
        /// <summary>
        /// The actual import hook that ties Python to the managed world.
        /// </summary>
        public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
        {
            // 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)"));
            }

            // borrowed reference
            IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);

            if (py_mod_name == IntPtr.Zero ||
                !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.

            IntPtr fromList = IntPtr.Zero;
            var    fromlist = false;

            if (num_args >= 4)
            {
                fromList = Runtime.PyTuple_GetItem(args, 3);
                if (fromList != IntPtr.Zero &&
                    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" || mod_name == "CLR")
            {
                if (mod_name == "CLR")
                {
                    Exceptions.deprecation("The CLR module is deprecated. Please use 'clr'.");
                }
                IntPtr clr_module = GetCLRModule(fromList);
                if (clr_module != IntPtr.Zero)
                {
                    IntPtr sys_modules = Runtime.PyImport_GetModuleDict();
                    if (sys_modules != IntPtr.Zero)
                    {
                        Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module);
                    }
                }
                return(clr_module);
            }

            string realname   = mod_name;
            string clr_prefix = null;

            if (mod_name.StartsWith("CLR."))
            {
                clr_prefix = "CLR."; // prepend when adding the module to sys.modules
                realname   = mod_name.Substring(4);
                string msg = $"Importing from the CLR.* namespace is deprecated. Please import '{realname}' directly.";
                Exceptions.deprecation(msg);
            }
            else
            {
                // 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, 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);
                }
                // Otherwise,  just clear the it.
                Exceptions.Clear();
            }

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

            // Now we need to decide if the name refers to a CLR module,
            // and may have to do an implicit load (for b/w compatibility)
            // using the AssemblyManager. The assembly manager tries
            // really hard not to use Python objects or APIs, because
            // parts of it can run recursively and on strange threads.
            //
            // It does need an opportunity from time to time to check to
            // see if sys.path has changed, in a context that is safe. Here
            // we know we have the GIL, so we'll let it update if needed.

            AssemblyManager.UpdatePath();
            if (!AssemblyManager.IsValidNamespace(realname))
            {
                var loadExceptions = new List <Exception>();
                if (!AssemblyManager.LoadImplicit(realname, assemblyLoadErrorHandler: loadExceptions.Add))
                {
                    // May be called when a module being imported imports a module.
                    // In particular, I've seen decimal import copy import org.python.core
                    IntPtr importResult = Runtime.PyObject_Call(py_import, args, kw);
                    // TODO: use ModuleNotFoundError in Python 3.6+
                    if (importResult == IntPtr.Zero && loadExceptions.Count > 0 &&
                        Exceptions.ExceptionMatches(Exceptions.ImportError))
                    {
                        loadExceptions.Add(new PythonException());
                        var importError = new PyObject(new BorrowedReference(Exceptions.ImportError));
                        importError.SetAttr("__cause__", new AggregateException(loadExceptions).ToPython());
                        Runtime.PyErr_SetObject(new BorrowedReference(Exceptions.ImportError), importError.Reference);
                    }
                    return(importResult);
                }
            }

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

            if (module != IntPtr.Zero)
            {
                if (fromlist)
                {
                    if (IsLoadAll(fromList))
                    {
                        var mod = ManagedType.GetManagedObject(module) as ModuleObject;
                        mod?.LoadNames();
                    }
                    Runtime.XIncref(module);
                    return(module);
                }
                if (clr_prefix != null)
                {
                    return(GetCLRModule(fromList));
                }
                module = Runtime.PyDict_GetItemString(modules, names[0]);
                Runtime.XIncref(module);
                return(module);
            }
            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))
                {
                    Exceptions.SetError(Exceptions.ImportError, $"No module named {name}");
                    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.pyHandle);

                // If imported from CLR add CLR.<modulename> to sys.modules as well
                if (clr_prefix != null)
                {
                    Runtime.PyDict_SetItemString(modules, clr_prefix + tail.moduleName, tail.pyHandle);
                }
            }

            {
                var mod = fromlist ? tail : head;

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

                Runtime.XIncref(mod.pyHandle);
                return(mod.pyHandle);
            }
        }
コード例 #8
0
ファイル: typemanager.cs プロジェクト: danielldx/pythonnet
        internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
        {
            var dictRef = new BorrowedReference(py_dict);
            // Utility to create a subtype of a managed type with the ability for the
            // a python subtype able to override the managed implementation
            string name = Runtime.GetManagedString(py_name);

            // the derived class can have class attributes __assembly__ and __module__ which
            // control the name of the assembly and module the new type is created in.
            object assembly     = null;
            object namespaceStr = null;

            using (var assemblyKey = new PyString("__assembly__"))
            {
                var assemblyPtr = Runtime.PyDict_GetItemWithError(dictRef, assemblyKey.Reference);
                if (assemblyPtr.IsNull)
                {
                    if (Exceptions.ErrorOccurred())
                    {
                        return(IntPtr.Zero);
                    }
                }
                else if (!Converter.ToManagedValue(assemblyPtr, typeof(string), out assembly, true))
                {
                    return(Exceptions.RaiseTypeError("Couldn't convert __assembly__ value to string"));
                }

                using (var namespaceKey = new PyString("__namespace__"))
                {
                    var pyNamespace = Runtime.PyDict_GetItemWithError(dictRef, namespaceKey.Reference);
                    if (pyNamespace.IsNull)
                    {
                        if (Exceptions.ErrorOccurred())
                        {
                            return(IntPtr.Zero);
                        }
                    }
                    else if (!Converter.ToManagedValue(pyNamespace, typeof(string), out namespaceStr, true))
                    {
                        return(Exceptions.RaiseTypeError("Couldn't convert __namespace__ value to string"));
                    }
                }
            }

            // create the new managed type subclassing the base managed type
            var baseClass = ManagedType.GetManagedObject(py_base_type) as ClassBase;

            if (null == baseClass)
            {
                return(Exceptions.RaiseTypeError("invalid base class, expected CLR class type"));
            }

            try
            {
                Type subType = ClassDerivedObject.CreateDerivedType(name,
                                                                    baseClass.type.Value,
                                                                    py_dict,
                                                                    (string)namespaceStr,
                                                                    (string)assembly);

                // create the new ManagedType and python type
                ClassBase subClass = ClassManager.GetClass(subType);
                IntPtr    py_type  = GetTypeHandle(subClass, subType);

                // by default the class dict will have all the C# methods in it, but as this is a
                // derived class we want the python overrides in there instead if they exist.
                var cls_dict = new BorrowedReference(Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict));
                ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, new BorrowedReference(py_dict)));
                Runtime.XIncref(py_type);
                // Update the __classcell__ if it exists
                BorrowedReference cell = Runtime.PyDict_GetItemString(cls_dict, "__classcell__");
                if (!cell.IsNull)
                {
                    ThrowIfIsNotZero(Runtime.PyCell_Set(cell, py_type));
                    ThrowIfIsNotZero(Runtime.PyDict_DelItemString(cls_dict, "__classcell__"));
                }

                return(py_type);
            }
            catch (Exception e)
            {
                return(Exceptions.RaiseTypeError(e.Message));
            }
        }
コード例 #9
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw,
                              MethodBase info)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;
            int          nargs    = Runtime.PyTuple_Size(args);
            object       arg;

            if (info != null)
            {
                _methods = (MethodBase[])Array.CreateInstance(
                    typeof(MethodBase), 1
                    );
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            for (int i = 0; i < _methods.Length; i++)
            {
                MethodBase      mi    = _methods[i];
                ParameterInfo[] pi    = mi.GetParameters();
                int             count = pi.Length;
                int             outs  = 0;

                if (nargs == count)
                {
                    Object[] margs = new Object[count];

                    for (int n = 0; n < count; n++)
                    {
                        IntPtr op   = Runtime.PyTuple_GetItem(args, n);
                        Type   type = pi[n].ParameterType;
                        if (pi[n].IsOut || type.IsByRef)
                        {
                            outs++;
                        }

                        if (!Converter.ToManaged(op, type, out arg, false))
                        {
                            Exceptions.Clear();
                            margs = null;
                            break;
                        }
                        margs[n] = arg;
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    Object target = null;
                    if ((!mi.IsStatic) && (inst != IntPtr.Zero))
                    {
                        CLRObject co = (CLRObject)ManagedType.GetManagedObject(
                            inst
                            );
                        target = co.inst;
                    }

                    return(new Binding(mi, target, margs, outs));
                }
            }
            return(null);
        }
コード例 #10
0
ファイル: typemanager.cs プロジェクト: zyhong/pythonnet
        internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
        {
            // Utility to create a subtype of a managed type with the ability for the
            // a python subtype able to override the managed implementation
            string name = Runtime.GetManagedString(py_name);

            // the derived class can have class attributes __assembly__ and __module__ which
            // control the name of the assembly and module the new type is created in.
            object assembly     = null;
            object namespaceStr = null;

            var disposeList = new List <PyObject>();

            try
            {
                var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string)));
                disposeList.Add(assemblyKey);
                if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle))
                {
                    var pyAssembly = new PyObject(Runtime.PyDict_GetItem(py_dict, assemblyKey.Handle));
                    Runtime.XIncref(pyAssembly.Handle);
                    disposeList.Add(pyAssembly);
                    if (!Converter.ToManagedValue(pyAssembly.Handle, typeof(string), out assembly, false))
                    {
                        throw new InvalidCastException("Couldn't convert __assembly__ value to string");
                    }
                }

                var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__"));
                disposeList.Add(namespaceKey);
                if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle))
                {
                    var pyNamespace = new PyObject(Runtime.PyDict_GetItem(py_dict, namespaceKey.Handle));
                    Runtime.XIncref(pyNamespace.Handle);
                    disposeList.Add(pyNamespace);
                    if (!Converter.ToManagedValue(pyNamespace.Handle, typeof(string), out namespaceStr, false))
                    {
                        throw new InvalidCastException("Couldn't convert __namespace__ value to string");
                    }
                }
            }
            finally
            {
                foreach (PyObject o in disposeList)
                {
                    o.Dispose();
                }
            }

            // create the new managed type subclassing the base managed type
            var baseClass = ManagedType.GetManagedObject(py_base_type) as ClassBase;

            if (null == baseClass)
            {
                return(Exceptions.RaiseTypeError("invalid base class, expected CLR class type"));
            }

            try
            {
                Type subType = ClassDerivedObject.CreateDerivedType(name,
                                                                    baseClass.type,
                                                                    py_dict,
                                                                    (string)namespaceStr,
                                                                    (string)assembly);

                // create the new ManagedType and python type
                ClassBase subClass = ClassManager.GetClass(subType);
                IntPtr    py_type  = GetTypeHandle(subClass, subType);

                // by default the class dict will have all the C# methods in it, but as this is a
                // derived class we want the python overrides in there instead if they exist.
                IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict);
                Runtime.PyDict_Update(cls_dict, py_dict);

                return(py_type);
            }
            catch (Exception e)
            {
                return(Exceptions.RaiseTypeError(e.Message));
            }
        }
コード例 #11
0
        /// <summary>
        /// Bind the given Python instance and arguments to a particular method
        /// overload in <see cref="list"/> and return a structure that contains the converted Python
        /// instance, converted arguments and the correct method to call.
        /// If unsuccessful, may set a Python error.
        /// </summary>
        /// <param name="inst">The Python target of the method invocation.</param>
        /// <param name="args">The Python arguments.</param>
        /// <param name="kw">The Python keyword arguments.</param>
        /// <param name="info">If not null, only bind to that method.</param>
        /// <param name="methodinfo">If not null, additionally attempt to bind to the generic methods in this array by inferring generic type parameters.</param>
        /// <returns>A Binding if successful.  Otherwise null.</returns>
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or w/o error
            MethodBase[] _methods = null;

            var kwargDict = new Dictionary <string, IntPtr>();

            if (kw != IntPtr.Zero)
            {
                var    pynkwargs = (int)Runtime.PyDict_Size(kw);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pynkwargs; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            var pynargs   = (int)Runtime.PyTuple_Size(args);
            var isGeneric = false;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            var argMatchedMethods = new List <MatchedMethod>(_methods.Length);
            var mismatchedMethods = new List <MismatchedMethod>();

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;
                int             kwargsMatched;
                int             defaultsNeeded;
                bool            isOperator = OperatorMethod.IsOperatorMethod(mi);
                // Binary operator methods will have 2 CLR args but only one Python arg
                // (unary operators will have 1 less each), since Python operator methods are bound.
                isOperator = isOperator && pynargs == pi.Length - 1;
                bool isReverse = isOperator && OperatorMethod.IsReverse((MethodInfo)mi);  // Only cast if isOperator.
                if (isReverse && OperatorMethod.IsComparisonOp((MethodInfo)mi))
                {
                    continue;  // Comparison operators in Python have no reverse mode.
                }
                if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList, out kwargsMatched, out defaultsNeeded) && !isOperator)
                {
                    continue;
                }
                // Preprocessing pi to remove either the first or second argument.
                if (isOperator && !isReverse)
                {
                    // The first Python arg is the right operand, while the bound instance is the left.
                    // We need to skip the first (left operand) CLR argument.
                    pi = pi.Skip(1).ToArray();
                }
                else if (isOperator && isReverse)
                {
                    // The first Python arg is the left operand.
                    // We need to take the first CLR argument.
                    pi = pi.Take(1).ToArray();
                }
                int outs;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList, outs: out outs);
                if (margs == null)
                {
                    var mismatchCause = PythonException.FetchCurrent();
                    mismatchedMethods.Add(new MismatchedMethod(mismatchCause, mi));
                    continue;
                }
                if (isOperator)
                {
                    if (inst != IntPtr.Zero)
                    {
                        if (ManagedType.GetManagedObject(inst) is CLRObject co)
                        {
                            bool isUnary = pynargs == 0;
                            // Postprocessing to extend margs.
                            var margsTemp = isUnary ? new object[1] : new object[2];
                            // If reverse, the bound instance is the right operand.
                            int boundOperandIndex = isReverse ? 1 : 0;
                            // If reverse, the passed instance is the left operand.
                            int passedOperandIndex = isReverse ? 0 : 1;
                            margsTemp[boundOperandIndex] = co.inst;
                            if (!isUnary)
                            {
                                margsTemp[passedOperandIndex] = margs[0];
                            }
                            margs = margsTemp;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }


                var matchedMethod = new MatchedMethod(kwargsMatched, defaultsNeeded, margs, outs, mi);
                argMatchedMethods.Add(matchedMethod);
            }
            if (argMatchedMethods.Count > 0)
            {
                var bestKwargMatchCount    = argMatchedMethods.Max(x => x.KwargsMatched);
                var fewestDefaultsRequired = argMatchedMethods.Where(x => x.KwargsMatched == bestKwargMatchCount).Min(x => x.DefaultsNeeded);

                int bestCount      = 0;
                int bestMatchIndex = -1;

                for (int index = 0; index < argMatchedMethods.Count; index++)
                {
                    var testMatch = argMatchedMethods[index];
                    if (testMatch.DefaultsNeeded == fewestDefaultsRequired && testMatch.KwargsMatched == bestKwargMatchCount)
                    {
                        bestCount++;
                        if (bestMatchIndex == -1)
                        {
                            bestMatchIndex = index;
                        }
                    }
                }

                if (bestCount > 1 && fewestDefaultsRequired > 0)
                {
                    // Best effort for determining method to match on gives multiple possible
                    // matches and we need at least one default argument - bail from this point
                    StringBuilder stringBuilder = new StringBuilder("Not enough arguments provided to disambiguate the method.  Found:");
                    foreach (var matchedMethod in argMatchedMethods)
                    {
                        stringBuilder.AppendLine();
                        stringBuilder.Append(matchedMethod.Method.ToString());
                    }
                    Exceptions.SetError(Exceptions.TypeError, stringBuilder.ToString());
                    return(null);
                }

                // If we're here either:
                //      (a) There is only one best match
                //      (b) There are multiple best matches but none of them require
                //          default arguments
                // in the case of (a) we're done by default. For (b) regardless of which
                // method we choose, all arguments are specified _and_ can be converted
                // from python to C# so picking any will suffice
                MatchedMethod bestMatch = argMatchedMethods[bestMatchIndex];
                var           margs     = bestMatch.ManagedArgs;
                var           outs      = bestMatch.Outs;
                var           mi        = bestMatch.Method;

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        Exceptions.SetError(Exceptions.TypeError, "Invoked a non-static method with an invalid instance");
                        return(null);
                    }
                    target = co.inst;
                }

                return(new Binding(mi, target, margs, outs));
            }
            else if (isGeneric && info == null && methodinfo != null)
            {
                // We weren't able to find a matching method but at least one
                // is a generic method and info is null. That happens when a generic
                // method was not called using the [] syntax. Let's introspect the
                // type of the arguments and use it to construct the correct method.
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                if (mi != null)
                {
                    return(Bind(inst, args, kw, mi, null));
                }
            }
            if (mismatchedMethods.Count > 0)
            {
                var aggregateException = GetAggregateException(mismatchedMethods);
                Exceptions.SetError(aggregateException);
            }
            return(null);
        }
コード例 #12
0
        //====================================================================
        // Implements __getitem__ for array types.
        //====================================================================

        public static IntPtr mp_subscript(IntPtr ob, IntPtr idx)
        {
            CLRObject obj      = (CLRObject)ManagedType.GetManagedObject(ob);
            Array     items    = obj.inst as Array;
            Type      itemType = obj.inst.GetType().GetElementType();
            int       rank     = items.Rank;
            int       index    = 0;
            object    value;

            // Note that CLR 1.0 only supports int indexes - methods to
            // support long indices were introduced in 1.1. We could
            // support long indices automatically, but given that long
            // indices are not backward compatible and a relative edge
            // case, we won't bother for now.

            // Single-dimensional arrays are the most common case and are
            // cheaper to deal with than multi-dimensional, so check first.

            if (rank == 1)
            {
                index = (int)Runtime.PyInt_AsLong(idx);

                if (Exceptions.ErrorOccurred())
                {
                    return(Exceptions.RaiseTypeError("invalid index value"));
                }

                if (index < 0)
                {
                    index = items.Length + index;
                }

                try {
                    value = items.GetValue(index);
                }
                catch (IndexOutOfRangeException) {
                    Exceptions.SetError(Exceptions.IndexError,
                                        "array index out of range"
                                        );
                    return(IntPtr.Zero);
                }

                return(Converter.ToPython(items.GetValue(index), itemType));
            }

            // Multi-dimensional arrays can be indexed a la: list[1, 2, 3].

            if (!Runtime.PyTuple_Check(idx))
            {
                Exceptions.SetError(Exceptions.TypeError,
                                    "invalid index value"
                                    );
                return(IntPtr.Zero);
            }

            int count = Runtime.PyTuple_Size(idx);

            Array args = Array.CreateInstance(typeof(Int32), count);

            for (int i = 0; i < count; i++)
            {
                IntPtr op = Runtime.PyTuple_GetItem(idx, i);
                index = (int)Runtime.PyInt_AsLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    return(Exceptions.RaiseTypeError("invalid index value"));
                }

                if (index < 0)
                {
                    index = items.GetLength(i) + index;
                }

                args.SetValue(index, i);
            }

            try {
                value = items.GetValue((int[])args);
            }
            catch (IndexOutOfRangeException) {
                Exceptions.SetError(Exceptions.IndexError,
                                    "array index out of range"
                                    );
                return(IntPtr.Zero);
            }

            return(Converter.ToPython(value, itemType));
        }
コード例 #13
0
        //====================================================================
        // This is the implementaion of the overriden methods in the derived
        // type. It looks for a python method with the same name as the method
        // on the managed base class and if it exists and isn't the managed
        // method binding (ie it has been overriden in the derived python
        // class) it calls it, otherwise it calls the base method.
        //====================================================================
        public static T InvokeMethod <T>(IPythonDerivedType obj, string methodName, string origMethodName, Object[] args)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            CLRObject self = (CLRObject)fi.GetValue(obj);

            if (null != self)
            {
                List <PyObject> disposeList = new List <PyObject>();
                IntPtr          gs          = Runtime.PyGILState_Ensure();
                try
                {
                    Runtime.Incref(self.pyHandle);
                    PyObject pyself = new PyObject(self.pyHandle);
                    disposeList.Add(pyself);

                    Runtime.Incref(Runtime.PyNone);
                    PyObject pynone = new PyObject(Runtime.PyNone);
                    disposeList.Add(pynone);

                    PyObject method = pyself.GetAttr(methodName, pynone);
                    disposeList.Add(method);
                    if (method.Handle != Runtime.PyNone)
                    {
                        // if the method hasn't been overriden then it will be a managed object
                        ManagedType managedMethod = ManagedType.GetManagedObject(method.Handle);
                        if (null == managedMethod)
                        {
                            PyObject[] pyargs = new PyObject[args.Length];
                            for (int i = 0; i < args.Length; ++i)
                            {
                                pyargs[i] = new PyObject(Converter.ToPythonImplicit(args[i]));
                                disposeList.Add(pyargs[i]);
                            }

                            PyObject py_result = method.Invoke(pyargs);
                            disposeList.Add(py_result);
                            return((T)py_result.AsManagedObject(typeof(T)));
                        }
                    }
                }
                finally
                {
                    foreach (PyObject x in disposeList)
                    {
                        if (x != null)
                        {
                            x.Dispose();
                        }
                    }
                    Runtime.PyGILState_Release(gs);
                }
            }

            if (origMethodName == null)
            {
                throw new NullReferenceException("Python object does not have a '" + methodName + "' method");
            }

            return((T)obj.GetType().InvokeMember(origMethodName,
                                                 BindingFlags.InvokeMethod,
                                                 null,
                                                 obj,
                                                 args));
        }
コード例 #14
0
        //====================================================================
        // Implements __setitem__ for array types.
        //====================================================================

        public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
        {
            CLRObject obj      = (CLRObject)ManagedType.GetManagedObject(ob);
            Array     items    = obj.inst as Array;
            Type      itemType = obj.inst.GetType().GetElementType();
            int       rank     = items.Rank;
            int       index    = 0;
            object    value;

            if (items.IsReadOnly)
            {
                Exceptions.RaiseTypeError("array is read-only");
                return(-1);
            }

            if (!Converter.ToManaged(v, itemType, out value, true))
            {
                return(-1);
            }

            if (rank == 1)
            {
                index = (int)Runtime.PyInt_AsLong(idx);

                if (Exceptions.ErrorOccurred())
                {
                    Exceptions.RaiseTypeError("invalid index value");
                    return(-1);
                }

                if (index < 0)
                {
                    index = items.Length + index;
                }

                try {
                    items.SetValue(value, index);
                }
                catch (IndexOutOfRangeException) {
                    Exceptions.SetError(Exceptions.IndexError,
                                        "array index out of range"
                                        );
                    return(-1);
                }

                return(0);
            }

            if (!Runtime.PyTuple_Check(idx))
            {
                Exceptions.RaiseTypeError("invalid index value");
                return(-1);
            }

            int count = Runtime.PyTuple_Size(idx);

            Array args = Array.CreateInstance(typeof(Int32), count);

            for (int i = 0; i < count; i++)
            {
                IntPtr op = Runtime.PyTuple_GetItem(idx, i);
                index = (int)Runtime.PyInt_AsLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Exceptions.RaiseTypeError("invalid index value");
                    return(-1);
                }

                if (index < 0)
                {
                    index = items.GetLength(i) + index;
                }

                args.SetValue(index, i);
            }

            try {
                items.SetValue(value, (int[])args);
            }
            catch (IndexOutOfRangeException) {
                Exceptions.SetError(Exceptions.IndexError,
                                    "array index out of range"
                                    );
                return(-1);
            }

            return(0);
        }
コード例 #15
0
        static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference)
        {
            isNewReference = false;
            IntPtr op;

            // for a params method, we may have a sequence or single/multiple items
            // here we look to see if the item at the paramIndex is there or not
            // and then if it is a sequence itself.
            if ((pyArgCount - arrayStart) == 1)
            {
                // Ee only have one argument left, so we need to check to see if it is a sequence or a single item
                // We also need to check if this object is possibly a wrapped C# Enumerable Object
                IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart);
                if (!Runtime.PyString_Check(item) && (Runtime.PySequence_Check(item) || (ManagedType.GetManagedObject(item) as CLRObject)?.inst is IEnumerable))
                {
                    // it's a sequence (and not a string), so we use it as the op
                    op = item;
                }
                else
                {
                    // Its a single value that needs to be converted into the params array
                    isNewReference = true;
                    op             = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
                }
            }
            else
            {
                // Its a set of individual values, so we grab them as a tuple to be converted into the params array
                isNewReference = true;
                op             = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
            }
            return(op);
        }
コード例 #16
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // Relevant function variables used post conversion
            var     isGeneric = false;
            Binding bindingUsingImplicitConversion = null;

            // If we have KWArgs create dictionary and collect them
            Dictionary <string, IntPtr> kwArgDict = null;

            if (kw != IntPtr.Zero)
            {
                var pyKwArgsCount = (int)Runtime.PyDict_Size(kw);
                kwArgDict = new Dictionary <string, IntPtr>(pyKwArgsCount);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pyKwArgsCount; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwArgDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            // Fetch our methods we are going to attempt to match and bind too.
            var methods = info == null?GetMethods()
                              : new List <MethodInformation>(1)
            {
                new MethodInformation(info, info.GetParameters())
            };

            foreach (var methodInformation in methods)
            {
                // Relevant method variables
                var mi = methodInformation.MethodBase;
                var pi = methodInformation.ParameterInfo;

                isGeneric = mi.IsGenericMethod;
                int pyArgCount = (int)Runtime.PyTuple_Size(args);


                // Special case for operators
                bool isOperator = OperatorMethod.IsOperatorMethod(mi);
                // Binary operator methods will have 2 CLR args but only one Python arg
                // (unary operators will have 1 less each), since Python operator methods are bound.
                isOperator = isOperator && pyArgCount == pi.Length - 1;
                bool isReverse = isOperator && OperatorMethod.IsReverse((MethodInfo)mi);  // Only cast if isOperator.
                if (isReverse && OperatorMethod.IsComparisonOp((MethodInfo)mi))
                {
                    continue;  // Comparison operators in Python have no reverse mode.
                }
                // Preprocessing pi to remove either the first or second argument.
                if (isOperator && !isReverse)
                {
                    // The first Python arg is the right operand, while the bound instance is the left.
                    // We need to skip the first (left operand) CLR argument.
                    pi = pi.Skip(1).ToArray();
                }
                else if (isOperator && isReverse)
                {
                    // The first Python arg is the left operand.
                    // We need to take the first CLR argument.
                    pi = pi.Take(1).ToArray();
                }

                // Must be done after IsOperator section
                int clrArgCount = pi.Length;

                if (CheckMethodArgumentsMatch(clrArgCount,
                                              pyArgCount,
                                              kwArgDict,
                                              pi,
                                              out bool paramsArray,
                                              out ArrayList defaultArgList))
                {
                    var outs  = 0;
                    var margs = new object[clrArgCount];

                    int paramsArrayIndex       = paramsArray ? pi.Length - 1 : -1; // -1 indicates no paramsArray
                    var usedImplicitConversion = false;

                    // Conversion loop for each parameter
                    for (int paramIndex = 0; paramIndex < clrArgCount; paramIndex++)
                    {
                        IntPtr op        = IntPtr.Zero;     // Python object to be converted; not yet set
                        var    parameter = pi[paramIndex];  // Clr parameter we are targeting
                        object arg;                         // Python -> Clr argument

                        // Check our KWargs for this parameter
                        bool hasNamedParam  = kwArgDict == null ? false : kwArgDict.TryGetValue(parameter.Name, out op);
                        bool isNewReference = false;

                        // Check if we are going to use default
                        if (paramIndex >= pyArgCount && !(hasNamedParam || (paramsArray && paramIndex == paramsArrayIndex)))
                        {
                            if (defaultArgList != null)
                            {
                                margs[paramIndex] = defaultArgList[paramIndex - pyArgCount];
                            }

                            continue;
                        }

                        // At this point, if op is IntPtr.Zero we don't have a KWArg and are not using default
                        if (op == IntPtr.Zero)
                        {
                            // If we have reached the paramIndex
                            if (paramsArrayIndex == paramIndex)
                            {
                                op = HandleParamsArray(args, paramsArrayIndex, pyArgCount, out isNewReference);
                            }
                            else
                            {
                                op = Runtime.PyTuple_GetItem(args, paramIndex);
                            }
                        }

                        // this logic below handles cases when multiple overloading methods
                        // are ambiguous, hence comparison between Python and CLR types
                        // is necessary
                        Type   clrtype = null;
                        IntPtr pyoptype;
                        if (methods.Count > 1)
                        {
                            pyoptype = IntPtr.Zero;
                            pyoptype = Runtime.PyObject_Type(op);
                            Exceptions.Clear();
                            if (pyoptype != IntPtr.Zero)
                            {
                                clrtype = Converter.GetTypeByAlias(pyoptype);
                            }
                            Runtime.XDecref(pyoptype);
                        }


                        if (clrtype != null)
                        {
                            var typematch = false;

                            if ((parameter.ParameterType != typeof(object)) && (parameter.ParameterType != clrtype))
                            {
                                IntPtr pytype = Converter.GetPythonTypeByAlias(parameter.ParameterType);
                                pyoptype = Runtime.PyObject_Type(op);
                                Exceptions.Clear();
                                if (pyoptype != IntPtr.Zero)
                                {
                                    if (pytype != pyoptype)
                                    {
                                        typematch = false;
                                    }
                                    else
                                    {
                                        typematch = true;
                                        clrtype   = parameter.ParameterType;
                                    }
                                }
                                if (!typematch)
                                {
                                    // this takes care of nullables
                                    var underlyingType = Nullable.GetUnderlyingType(parameter.ParameterType);
                                    if (underlyingType == null)
                                    {
                                        underlyingType = parameter.ParameterType;
                                    }
                                    // this takes care of enum values
                                    TypeCode argtypecode   = Type.GetTypeCode(underlyingType);
                                    TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                                    if (argtypecode == paramtypecode)
                                    {
                                        typematch = true;
                                        clrtype   = parameter.ParameterType;
                                    }
                                    // accepts non-decimal numbers in decimal parameters
                                    if (underlyingType == typeof(decimal))
                                    {
                                        clrtype   = parameter.ParameterType;
                                        typematch = Converter.ToManaged(op, clrtype, out arg, false);
                                    }
                                    // this takes care of implicit conversions
                                    var opImplicit = parameter.ParameterType.GetMethod("op_Implicit", new[] { clrtype });
                                    if (opImplicit != null)
                                    {
                                        usedImplicitConversion = typematch = opImplicit.ReturnType == parameter.ParameterType;
                                        clrtype = parameter.ParameterType;
                                    }
                                }
                                Runtime.XDecref(pyoptype);
                                if (!typematch)
                                {
                                    margs = null;
                                    break;
                                }
                            }
                            else
                            {
                                clrtype = parameter.ParameterType;
                            }
                        }
                        else
                        {
                            clrtype = parameter.ParameterType;
                        }

                        if (parameter.IsOut || clrtype.IsByRef)
                        {
                            outs++;
                        }

                        if (!Converter.ToManaged(op, clrtype, out arg, false))
                        {
                            Exceptions.Clear();
                            margs = null;
                            break;
                        }

                        if (isNewReference)
                        {
                            // TODO: is this a bug? Should this happen even if the conversion fails?
                            // GetSlice() creates a new reference but GetItem()
                            // returns only a borrow reference.
                            Runtime.XDecref(op);
                        }

                        margs[paramIndex] = arg;
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    if (isOperator)
                    {
                        if (inst != IntPtr.Zero)
                        {
                            if (ManagedType.GetManagedObject(inst) is CLRObject co)
                            {
                                bool isUnary = pyArgCount == 0;
                                // Postprocessing to extend margs.
                                var margsTemp = isUnary ? new object[1] : new object[2];
                                // If reverse, the bound instance is the right operand.
                                int boundOperandIndex = isReverse ? 1 : 0;
                                // If reverse, the passed instance is the left operand.
                                int passedOperandIndex = isReverse ? 0 : 1;
                                margsTemp[boundOperandIndex] = co.inst;
                                if (!isUnary)
                                {
                                    margsTemp[passedOperandIndex] = margs[0];
                                }
                                margs = margsTemp;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }

                    object target = null;
                    if (!mi.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    var binding = new Binding(mi, target, margs, outs);
                    if (usedImplicitConversion)
                    {
                        // lets just keep the first binding using implicit conversion
                        // this is to respect method order/precedence
                        if (bindingUsingImplicitConversion == null)
                        {
                            // in this case we will not return the binding yet in case there is a match
                            // which does not use implicit conversions, which will return directly
                            bindingUsingImplicitConversion = binding;
                        }
                    }
                    else
                    {
                        return(binding);
                    }
                }
            }

            // if we generated a binding using implicit conversion return it
            if (bindingUsingImplicitConversion != null)
            {
                return(bindingUsingImplicitConversion);
            }

            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
コード例 #17
0
        internal Binding Bind(IntPtr inst, IntPtr pythonParametersPtr, IntPtr kw, MethodBase info, MethodInfo[] methodInfoArray)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;
            // NOTE: return the size of the args pointer (the number of parameter from the python call)
            int pythonParameterCount = Runtime.PyTuple_Size(pythonParametersPtr);
            //WHY: Why is that so widely scoped ?
            object    pythonManagedParameterPtr;
            var       isGeneric            = false;
            ArrayList defaultParameterList = null;

            if (info != null)
            {
                // NOTE: If a MethodBase object has been provided, create an array with only it.
                // WHY a method base is provided some times and not other ? (ex: when call a genric with a type in [])
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                // NOTE: Create an array of MethodBase from teh called method/constructor
                // WHY not use the methodinfo provided?
                _methods = GetMethods();
            }
            //WHY is it so widely scoped
            Type clrConvertedParameterType;

            // TODO: Clean up
            foreach (MethodBase methodInfo in _methods)
            {
                //WHY not just do isGeneric = mi.IsGenericMethod or use it directly ?
                if (methodInfo.IsGenericMethod)
                {
                    isGeneric = true;
                }
                //NOTE: Get the parameter from the current MethodBase
                //NOTE: MethodInfo Ok
                ParameterInfo[] clrParameterInfoArray = methodInfo.GetParameters();
                //NOTE: Get the number of clr parameters
                int clrParameterCount = clrParameterInfoArray.Length;

                var paramCountMatch = false;
                //REFACTOR: Use var like the other local variables
                var clrHasParamArray    = false;
                var clrParamsArrayStart = -1;

                var byRefCount = 0;

                if (pythonParameterCount == clrParameterCount)
                {
                    paramCountMatch = true;
                }
                else if (pythonParameterCount < clrParameterCount)
                {
                    paramCountMatch      = true;
                    defaultParameterList = new ArrayList();
                    for (int v = pythonParameterCount; v < clrParameterCount; v++)
                    {
                        if (clrParameterInfoArray[v].DefaultValue == DBNull.Value)
                        {
                            paramCountMatch = false;
                        }
                        else
                        {
                            defaultParameterList.Add(clrParameterInfoArray[v].DefaultValue);
                        }
                    }
                }
                else if (pythonParameterCount > clrParameterCount && clrParameterCount > 0 &&
                         Attribute.IsDefined(clrParameterInfoArray[clrParameterCount - 1], typeof(ParamArrayAttribute)))
                {
                    // This is a `foo({...}, params object[] bar)` style method
                    paramCountMatch     = true;
                    clrHasParamArray    = true;
                    clrParamsArrayStart = clrParameterCount - 1;
                }

                if (paramCountMatch)
                {
                    var methodParametersPtrArray = new object[clrParameterCount];

                    for (var n = 0; n < clrParameterCount; n++)
                    {
                        IntPtr pythonParameterPtr;
                        if (n < pythonParameterCount)
                        {
                            if (clrParamsArrayStart == n)
                            {
                                // map remaining Python arguments to a tuple since
                                // the managed function accepts it - hopefully :]
                                //WHY: Hmmm it returns a lot of python paramter as one. isn't there a problem later ?
                                pythonParameterPtr = Runtime.PyTuple_GetSlice(pythonParametersPtr, clrParamsArrayStart, pythonParameterCount);
                            }
                            else
                            {
                                pythonParameterPtr = Runtime.PyTuple_GetItem(pythonParametersPtr, n);
                            }

                            // this logic below handles cases when multiple overloading methods
                            // are ambiguous, hence comparison between Python and CLR types
                            // is necessary
                            clrConvertedParameterType = null;
                            IntPtr pythonParameterPtrType = IntPtr.Zero;
                            if (_methods.Length > 1)
                            {
                                pythonParameterPtrType = Runtime.PyObject_Type(pythonParameterPtr);
                                Exceptions.Clear();
                                if (pythonParameterPtrType != IntPtr.Zero)
                                {
                                    clrConvertedParameterType = Converter.GetTypeByAlias(pythonParameterPtrType);
                                }
                                Runtime.XDecref(pythonParameterPtrType);
                            }


                            if (clrConvertedParameterType != null)
                            {
                                var parameterTypeMatch = false;
                                if ((clrParameterInfoArray[n].ParameterType != typeof(object)) && (clrParameterInfoArray[n].ParameterType != clrConvertedParameterType))
                                {
                                    IntPtr pythonConvertedParameterPtrType = Converter.GetPythonTypeByAlias(clrParameterInfoArray[n].ParameterType);
                                    pythonParameterPtrType = Runtime.PyObject_Type(pythonParameterPtr);
                                    Exceptions.Clear();
                                    if (pythonParameterPtrType != IntPtr.Zero)
                                    {
                                        if (pythonConvertedParameterPtrType != pythonParameterPtrType)
                                        {
                                            parameterTypeMatch = false;
                                        }
                                        else
                                        {
                                            parameterTypeMatch        = true;
                                            clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                                        }
                                    }
                                    if (!parameterTypeMatch)
                                    {
                                        // this takes care of enum values
                                        TypeCode clrParameterTypeCode          = Type.GetTypeCode(clrParameterInfoArray[n].ParameterType);
                                        TypeCode clrConvertedParameterTypeCode = Type.GetTypeCode(clrConvertedParameterType);
                                        if (clrParameterTypeCode == clrConvertedParameterTypeCode)
                                        {
                                            parameterTypeMatch        = true;
                                            clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                                        }
                                    }
                                    Runtime.XDecref(pythonParameterPtrType);
                                    if (!parameterTypeMatch)
                                    {
                                        methodParametersPtrArray = null;
                                        break;
                                    }
                                }
                                else
                                {
                                    parameterTypeMatch        = true;
                                    clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                                }
                            }
                            else
                            {
                                clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                            }

                            if (clrParameterInfoArray[n].IsOut || clrConvertedParameterType.IsByRef)
                            {
                                byRefCount++;
                            }

                            if (!Converter.ToManaged(pythonParameterPtr, clrConvertedParameterType, out pythonManagedParameterPtr, false))
                            {
                                Exceptions.Clear();
                                methodParametersPtrArray = null;
                                break;
                            }
                            if (clrParamsArrayStart == n)
                            {
                                // GetSlice() creates a new reference but GetItem()
                                // returns only a borrow reference.
                                Runtime.XDecref(pythonParameterPtr);
                            }
                            methodParametersPtrArray[n] = pythonParameterPtr;
                        }
                        else
                        {
                            if (defaultParameterList != null)
                            {
                                methodParametersPtrArray[n] = defaultParameterList[n - pythonParameterCount];
                            }
                        }
                    }

                    if (methodParametersPtrArray == null)
                    {
                        continue;
                    }

                    object target = null;
                    if (!methodInfo.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    return(new Binding(methodInfo, target, methodParametersPtrArray, byRefCount));
                }
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodInfoArray != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(pythonParametersPtr, true);
                MethodInfo mi    = MatchParameters(methodInfoArray, types);
                return(Bind(inst, pythonParametersPtr, kw, mi, null));
            }
            return(null);
        }
コード例 #18
0
ファイル: methodbinder.cs プロジェクト: fkarb/pythonnet_old
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw,
                              MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;
            int          pynargs  = Runtime.PyTuple_Size(args);
            object       arg;
            bool         isGeneric = false;

            if (info != null)
            {
                _methods = (MethodBase[])Array.CreateInstance(
                    typeof(MethodBase), 1
                    );
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            for (int i = 0; i < _methods.Length; i++)
            {
                MethodBase mi = _methods[i];
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi         = mi.GetParameters();
                int             clrnargs   = pi.Length;
                bool            match      = false;
                int             arrayStart = -1;
                int             outs       = 0;

                if (pynargs == clrnargs)
                {
                    match = true;
                }
                else if ((pynargs > clrnargs) && (clrnargs > 0) &&
                         (pi[clrnargs - 1].ParameterType.IsArray))
                {
                    // The last argument of the mananged functions seems to
                    // accept multiple arguments as a array. Hopefully it's a
                    // spam(params object[] egg) style method
                    match      = true;
                    arrayStart = clrnargs - 1;
                }

                if (match)
                {
                    Object[] margs = new Object[clrnargs];

                    for (int n = 0; n < clrnargs; n++)
                    {
                        IntPtr op;
                        if (arrayStart == n)
                        {
                            // map remaining Python arguments to a tuple since
                            // the managed function accepts it - hopefully :]
                            op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
                        }
                        else
                        {
                            op = Runtime.PyTuple_GetItem(args, n);
                        }
                        Type type = pi[n].ParameterType;
                        if (pi[n].IsOut || type.IsByRef)
                        {
                            outs++;
                        }

                        if (!Converter.ToManaged(op, type, out arg, false))
                        {
                            Exceptions.Clear();
                            margs = null;
                            break;
                        }
                        if (arrayStart == n)
                        {
                            // GetSlice() creates a new reference but GetItem()
                            // returns only a borrow reference.
                            Runtime.Decref(op);
                        }
                        margs[n] = arg;
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    Object target = null;
                    if ((!mi.IsStatic) && (inst != IntPtr.Zero))
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        CLRObject co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    return(new Binding(mi, target, margs, outs));
                }
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && (info == null) && (methodinfo != null))
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MethodBinder.MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
コード例 #19
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            int       pynargs = Runtime.PyTuple_Size(args);
            object    arg;
            var       isGeneric = false;
            ArrayList defaultArgList;
            Type      clrtype;
            Binding   bindingUsingImplicitConversion = null;

            var methods = info == null?GetMethods()
                              : new List <MethodInformation>(1)
            {
                new MethodInformation(info, info.GetParameters())
            };

            // TODO: Clean up
            foreach (var methodInformation in methods)
            {
                var mi = methodInformation.MethodBase;
                var pi = methodInformation.ParameterInfo;

                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                int clrnargs = pi.Length;
                int arrayStart;

                if (CheckMethodArgumentsMatch(clrnargs,
                                              pynargs,
                                              pi,
                                              out arrayStart,
                                              out defaultArgList))
                {
                    var outs  = 0;
                    var margs = new object[clrnargs];
                    var usedImplicitConversion = false;

                    for (var n = 0; n < clrnargs; n++)
                    {
                        IntPtr op;
                        if (n < pynargs)
                        {
                            if (arrayStart == n)
                            {
                                // map remaining Python arguments to a tuple since
                                // the managed function accepts it - hopefully :]
                                op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
                            }
                            else
                            {
                                op = Runtime.PyTuple_GetItem(args, n);
                            }

                            // this logic below handles cases when multiple overloading methods
                            // are ambiguous, hence comparison between Python and CLR types
                            // is necessary
                            clrtype = null;
                            IntPtr pyoptype;
                            if (methods.Count > 1)
                            {
                                pyoptype = IntPtr.Zero;
                                pyoptype = Runtime.PyObject_Type(op);
                                Exceptions.Clear();
                                if (pyoptype != IntPtr.Zero)
                                {
                                    clrtype = Converter.GetTypeByAlias(pyoptype);
                                }
                                Runtime.XDecref(pyoptype);
                            }


                            if (clrtype != null)
                            {
                                var typematch = false;
                                if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype))
                                {
                                    IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType);
                                    pyoptype = Runtime.PyObject_Type(op);
                                    Exceptions.Clear();
                                    if (pyoptype != IntPtr.Zero)
                                    {
                                        if (pytype != pyoptype)
                                        {
                                            typematch = false;
                                        }
                                        else
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                    }
                                    if (!typematch)
                                    {
                                        // this takes care of nullables
                                        var underlyingType = Nullable.GetUnderlyingType(pi[n].ParameterType);
                                        if (underlyingType == null)
                                        {
                                            underlyingType = pi[n].ParameterType;
                                        }
                                        // this takes care of enum values
                                        TypeCode argtypecode   = Type.GetTypeCode(underlyingType);
                                        TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                                        if (argtypecode == paramtypecode)
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                        // accepts non-decimal numbers in decimal parameters
                                        if (underlyingType == typeof(decimal))
                                        {
                                            clrtype   = pi[n].ParameterType;
                                            typematch = Converter.ToManaged(op, clrtype, out arg, false);
                                        }
                                        // this takes care of implicit conversions
                                        var opImplicit = pi[n].ParameterType.GetMethod("op_Implicit", new[] { clrtype });
                                        if (opImplicit != null)
                                        {
                                            usedImplicitConversion = typematch = opImplicit.ReturnType == pi[n].ParameterType;
                                            clrtype = pi[n].ParameterType;
                                        }
                                    }
                                    Runtime.XDecref(pyoptype);
                                    if (!typematch)
                                    {
                                        margs = null;
                                        break;
                                    }
                                }
                                else
                                {
                                    typematch = true;
                                    clrtype   = pi[n].ParameterType;
                                }
                            }
                            else
                            {
                                clrtype = pi[n].ParameterType;
                            }

                            if (pi[n].IsOut || clrtype.IsByRef)
                            {
                                outs++;
                            }

                            if (!Converter.ToManaged(op, clrtype, out arg, false))
                            {
                                Exceptions.Clear();
                                margs = null;
                                break;
                            }
                            if (arrayStart == n)
                            {
                                // GetSlice() creates a new reference but GetItem()
                                // returns only a borrow reference.
                                Runtime.XDecref(op);
                            }
                            margs[n] = arg;
                        }
                        else
                        {
                            if (defaultArgList != null)
                            {
                                margs[n] = defaultArgList[n - pynargs];
                            }
                        }
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    object target = null;
                    if (!mi.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    var binding = new Binding(mi, target, margs, outs);
                    if (usedImplicitConversion)
                    {
                        // lets just keep the first binding using implicit conversion
                        // this is to respect method order/precedence
                        if (bindingUsingImplicitConversion == null)
                        {
                            // in this case we will not return the binding yet in case there is a match
                            // which does not use implicit conversions, which will return directly
                            bindingUsingImplicitConversion = binding;
                        }
                    }
                    else
                    {
                        return(binding);
                    }
                }
            }

            // if we generated a binding using implicit conversion return it
            if (bindingUsingImplicitConversion != null)
            {
                return(bindingUsingImplicitConversion);
            }

            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
コード例 #20
0
        public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName,
                                            object[] args)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            if (null != self)
            {
                var    disposeList = new List <PyObject>();
                IntPtr gs          = Runtime.PyGILState_Ensure();
                try
                {
                    Runtime.XIncref(self.pyHandle);
                    var pyself = new PyObject(self.pyHandle);
                    disposeList.Add(pyself);

                    Runtime.XIncref(Runtime.PyNone);
                    var pynone = new PyObject(Runtime.PyNone);
                    disposeList.Add(pynone);

                    PyObject method = pyself.GetAttr(methodName, pynone);
                    disposeList.Add(method);
                    if (method.Handle != Runtime.PyNone)
                    {
                        // if the method hasn't been overridden then it will be a managed object
                        ManagedType managedMethod = ManagedType.GetManagedObject(method.Handle);
                        if (null == managedMethod)
                        {
                            var pyargs = new PyObject[args.Length];
                            for (var i = 0; i < args.Length; ++i)
                            {
                                pyargs[i] = new PyObject(Converter.ToPythonImplicit(args[i]));
                                disposeList.Add(pyargs[i]);
                            }

                            PyObject py_result = method.Invoke(pyargs);
                            disposeList.Add(py_result);
                            return;
                        }
                    }
                }
                finally
                {
                    foreach (PyObject x in disposeList)
                    {
                        x?.Dispose();
                    }
                    Runtime.PyGILState_Release(gs);
                }
            }

            if (origMethodName == null)
            {
                throw new NotImplementedException($"Python object does not have a '{methodName}' method");
            }

            obj.GetType().InvokeMember(origMethodName,
                                       BindingFlags.InvokeMethod,
                                       null,
                                       obj,
                                       args);
        }
コード例 #21
0
        public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, Object[] args)
        {
            // call the base constructor
            obj.GetType().InvokeMember(origCtorName,
                                       BindingFlags.InvokeMethod,
                                       null,
                                       obj,
                                       args);

            List <PyObject> disposeList = new List <PyObject>();
            CLRObject       self        = null;
            IntPtr          gs          = Runtime.PyGILState_Ensure();

            try
            {
                // create the python object
                IntPtr type = TypeManager.GetTypeHandle(obj.GetType());
                self = new CLRObject(obj, type);

                // set __pyobj__ to self and deref the python object which will allow this
                // object to be collected.
                FieldInfo fi = obj.GetType().GetField("__pyobj__");
                fi.SetValue(obj, self);

                Runtime.Incref(self.pyHandle);
                PyObject pyself = new PyObject(self.pyHandle);
                disposeList.Add(pyself);

                Runtime.Incref(Runtime.PyNone);
                PyObject pynone = new PyObject(Runtime.PyNone);
                disposeList.Add(pynone);

                // call __init__
                PyObject init = pyself.GetAttr("__init__", pynone);
                disposeList.Add(init);
                if (init.Handle != Runtime.PyNone)
                {
                    // if __init__ hasn't been overriden then it will be a managed object
                    ManagedType managedMethod = ManagedType.GetManagedObject(init.Handle);
                    if (null == managedMethod)
                    {
                        PyObject[] pyargs = new PyObject[args.Length];
                        for (int i = 0; i < args.Length; ++i)
                        {
                            pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i].GetType()));
                            disposeList.Add(pyargs[i]);
                        }

                        disposeList.Add(init.Invoke(pyargs));
                    }
                }
            }
            finally
            {
                foreach (PyObject x in disposeList)
                {
                    if (x != null)
                    {
                        x.Dispose();
                    }
                }

                // Decrement the python object's reference count.
                // This doesn't actually destroy the object, it just sets the reference to this object
                // to be a weak reference and it will be destroyed when the C# object is destroyed.
                if (null != self)
                {
                    Runtime.Decref(self.pyHandle);
                }

                Runtime.PyGILState_Release(gs);
            }
        }
コード例 #22
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;

            var kwargDict = new Dictionary <string, IntPtr>();

            if (kw != IntPtr.Zero)
            {
                var    pynkwargs = (int)Runtime.PyDict_Size(kw);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pynkwargs; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            var pynargs   = (int)Runtime.PyTuple_Size(args);
            var isGeneric = false;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            var argMatchedMethods = new List <MatchedMethod>(_methods.Length);

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;
                int             kwargsMatched;
                int             defaultsNeeded;

                if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList, out kwargsMatched, out defaultsNeeded))
                {
                    continue;
                }
                var outs  = 0;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList,
                                                needsResolution: _methods.Length > 1,
                                                outs: out outs);

                if (margs == null)
                {
                    continue;
                }

                var matchedMethod = new MatchedMethod(kwargsMatched, defaultsNeeded, margs, outs, mi);
                argMatchedMethods.Add(matchedMethod);
            }
            if (argMatchedMethods.Count > 0)
            {
                var bestKwargMatchCount    = argMatchedMethods.Max(x => x.KwargsMatched);
                var fewestDefaultsRequired = argMatchedMethods.Where(x => x.KwargsMatched == bestKwargMatchCount).Min(x => x.DefaultsNeeded);

                int bestCount      = 0;
                int bestMatchIndex = -1;

                for (int index = 0; index < argMatchedMethods.Count; index++)
                {
                    var testMatch = argMatchedMethods[index];
                    if (testMatch.DefaultsNeeded == fewestDefaultsRequired && testMatch.KwargsMatched == bestKwargMatchCount)
                    {
                        bestCount++;
                        if (bestMatchIndex == -1)
                        {
                            bestMatchIndex = index;
                        }
                    }
                }

                if (bestCount > 1 && fewestDefaultsRequired > 0)
                {
                    // Best effort for determining method to match on gives multiple possible
                    // matches and we need at least one default argument - bail from this point
                    return(null);
                }

                // If we're here either:
                //      (a) There is only one best match
                //      (b) There are multiple best matches but none of them require
                //          default arguments
                // in the case of (a) we're done by default. For (b) regardless of which
                // method we choose, all arguments are specified _and_ can be converted
                // from python to C# so picking any will suffice
                MatchedMethod bestMatch = argMatchedMethods[bestMatchIndex];
                var           margs     = bestMatch.ManagedArgs;
                var           outs      = bestMatch.Outs;
                var           mi        = bestMatch.Method;

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        return(null);
                    }
                    target = co.inst;
                }

                return(new Binding(mi, target, margs, outs));
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
コード例 #23
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;

            var kwargDict = new Dictionary <string, IntPtr>();

            if (kw != IntPtr.Zero)
            {
                var    pynkwargs = (int)Runtime.PyDict_Size(kw);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pynkwargs; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            var pynargs   = (int)Runtime.PyTuple_Size(args);
            var isGeneric = false;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;

                if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList))
                {
                    continue;
                }
                var outs  = 0;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList,
                                                needsResolution: _methods.Length > 1,
                                                outs: out outs);

                if (margs == null)
                {
                    continue;
                }

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        return(null);
                    }
                    target = co.inst;
                }

                return(new Binding(mi, target, margs, outs));
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
コード例 #24
0
        internal static bool ToManagedValue(BorrowedReference value, Type obType,
                                            out object?result, bool setError)
        {
            if (obType == typeof(PyObject))
            {
                result = new PyObject(value);
                return(true);
            }

            if (obType.IsSubclassOf(typeof(PyObject)) &&
                !obType.IsAbstract &&
                obType.GetConstructor(new[] { typeof(PyObject) }) is { } ctor)
            {
                var untyped = new PyObject(value);
                result = ToPyObjectSubclass(ctor, untyped, setError);
                return(result is not null);
            }

            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            result = null;
            switch (ManagedType.GetManagedObject(value))
            {
            case CLRObject co:
                object tmp = co.inst;
                if (obType.IsInstanceOfType(tmp))
                {
                    result = tmp;
                    return(true);
                }
                if (setError)
                {
                    string typeString = tmp is null ? "null" : tmp.GetType().ToString();
                    Exceptions.SetError(Exceptions.TypeError, $"{typeString} value cannot be converted to {obType}");
                }
                return(false);

            case ClassBase cb:
                if (!cb.type.Valid)
                {
                    Exceptions.SetError(Exceptions.TypeError, cb.type.DeletedMessage);
                    return(false);
                }
                result = cb.type.Value;
                return(true);

            case null:
                break;

            default:
                throw new ArgumentException("We should never receive instances of other managed types");
            }

            if (value == Runtime.PyNone && !obType.IsValueType)
            {
                result = null;
                return(true);
            }

            if (obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (value == Runtime.PyNone)
                {
                    result = null;
                    return(true);
                }
                // Set type to underlying type
                obType = obType.GetGenericArguments()[0];
            }

            if (obType.ContainsGenericParameters)
            {
                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, $"Cannot create an instance of the open generic type {obType}");
                }
                return(false);
            }

            if (obType.IsArray)
            {
                return(ToArray(value, obType, out result, setError));
            }

            // Conversion to 'Object' is done based on some reasonable default
            // conversions (Python string -> managed string).
            if (obType == objectType)
            {
                if (Runtime.IsStringType(value))
                {
                    return(ToPrimitive(value, stringType, out result, setError));
                }

                if (Runtime.PyBool_Check(value))
                {
                    return(ToPrimitive(value, boolType, out result, setError));
                }

                if (Runtime.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

                // give custom codecs a chance to take over conversion of ints and sequences
                BorrowedReference pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }

                if (Runtime.PyInt_Check(value))
                {
                    result = new PyInt(value);
                    return(true);
                }

                if (Runtime.PySequence_Check(value))
                {
                    return(ToArray(value, typeof(object[]), out result, setError));
                }

                result = new PyObject(value);
                return(true);
            }

            // Conversion to 'Type' is done using the same mappings as above for objects.
            if (obType == typeType)
            {
                if (value == Runtime.PyStringType)
                {
                    result = stringType;
                    return(true);
                }

                if (value == Runtime.PyBoolType)
                {
                    result = boolType;
                    return(true);
                }

                if (value == Runtime.PyLongType)
                {
                    result = typeof(PyInt);
                    return(true);
                }

                if (value == Runtime.PyFloatType)
                {
                    result = doubleType;
                    return(true);
                }

                if (value == Runtime.PyListType)
                {
                    result = typeof(PyList);
                    return(true);
                }

                if (value == Runtime.PyTupleType)
                {
                    result = typeof(PyTuple);
                    return(true);
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type");
                }

                return(false);
            }

            if (DecodableByUser(obType))
            {
                BorrowedReference pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
コード例 #25
0
        internal List <Binding> Bind(IntPtr inst, IntPtr args, IntPtr kw, Type type, MethodBase info, MethodInfo[] methodinfo)
        {
            #region COM Binding

            List <Binding> bindings = new List <Binding>();

            #endregion


            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods  = null;
            var          pynargs   = (int)Runtime.PyTuple_Size(args);
            var          isGeneric = false;
            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                #region COM Binding

                try
                {
                    // Enforcable return types
                    if (type != null)
                    {
                        if (!(type.IsSubclassOf(((MethodInfo)mi).ReturnType) ||
                              type.Equals(((MethodInfo)mi).ReturnType)))
                        {
                            continue;
                        }
                    }
                }
                catch (InvalidCastException ex) { }

                #endregion

                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi = mi.GetParameters();
                ArrayList       defaultArgList;
                bool            paramsArray;

                if (!MatchesArgumentCount(pynargs, pi, out paramsArray, out defaultArgList))
                {
                    continue;
                }
                var outs  = 0;
                var margs = TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList,
                                                needsResolution: _methods.Length > 1,
                                                outs: out outs);

                if (margs == null)
                {
                    continue;
                }

                object target = null;
                if (!mi.IsStatic && inst != IntPtr.Zero)
                {
                    //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                    // InvalidCastException: Unable to cast object of type
                    // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                    var co = ManagedType.GetManagedObject(inst) as CLRObject;

                    // Sanity check: this ensures a graceful exit if someone does
                    // something intentionally wrong like call a non-static method
                    // on the class rather than on an instance of the class.
                    // XXX maybe better to do this before all the other rigmarole.
                    if (co == null)
                    {
                        return(new List <Binding>());
                    }
                    target = co.inst;
                }

                #region COM Binding

                bindings.Add(new Binding(mi, target, margs, outs));
                //return new Binding(mi, target, margs, outs);

                #endregion
            }

            #region COM Binding

            if (bindings.Count > 0)
            {
                /*Binding item = bindings.Where<Binding>(x => x.info.Name.EndsWith("_Item")).FirstOrDefault<Binding>();
                 * if (item != null)
                 *  return item;
                 *
                 * Binding def = bindings.Where<Binding>(x => x.info.Name.EndsWith("_Default")).FirstOrDefault<Binding>();
                 * if (def != null)
                 *  return def;
                 *
                 * return bindings.First<Binding>();*/

                return(bindings.OrderBy(x => x.info.Name).ToList <Binding>());
            }

            #endregion

            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, type, mi, null));
            }
            return(new List <Binding>());
        }
コード例 #26
0
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out object result, bool setError, out bool usedImplicit)
        {
            usedImplicit = false;
            if (obType == typeof(PyObject))
            {
                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            if (obType.IsGenericType && Runtime.PyObject_TYPE(value) == Runtime.PyListType)
            {
                var typeDefinition = obType.GetGenericTypeDefinition();
                if (typeDefinition == typeof(List <>))
                {
                    return(ToList(value, obType, out result, setError));
                }
            }

            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            ManagedType mt = ManagedType.GetManagedObject(value);

            result = null;

            if (mt != null)
            {
                if (mt is CLRObject co)
                {
                    object tmp = co.inst;
                    if (obType.IsInstanceOfType(tmp))
                    {
                        result = tmp;
                        return(true);
                    }
                    else
                    {
                        var type = tmp.GetType();
                        // check implicit conversions that receive tmp type and return obType
                        var conversionMethod = type.GetMethod("op_Implicit", new[] { type });
                        if (conversionMethod != null && conversionMethod.ReturnType == obType)
                        {
                            result       = conversionMethod.Invoke(null, new[] { tmp });
                            usedImplicit = true;
                            return(true);
                        }
                    }
                    if (setError)
                    {
                        string typeString = tmp is null ? "null" : tmp.GetType().ToString();
                        Exceptions.SetError(Exceptions.TypeError, $"{typeString} value cannot be converted to {obType}");
                    }
                    return(false);
                }
                if (mt is ClassBase cb)
                {
                    if (!cb.type.Valid)
                    {
                        Exceptions.SetError(Exceptions.TypeError, cb.type.DeletedMessage);
                        return(false);
                    }
                    result = cb.type.Value;
                    return(true);
                }
                // shouldn't happen
                return(false);
            }

            if (value == Runtime.PyNone && !obType.IsValueType)
            {
                result = null;
                return(true);
            }

            if (obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (value == Runtime.PyNone)
                {
                    result = null;
                    return(true);
                }
                // Set type to underlying type
                obType = obType.GetGenericArguments()[0];
            }

            if (obType.ContainsGenericParameters)
            {
                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, $"Cannot create an instance of the open generic type {obType}");
                }
                return(false);
            }

            if (obType.IsArray)
            {
                return(ToArray(value, obType, out result, setError));
            }

            if (obType.IsEnum)
            {
                return(ToEnum(value, obType, out result, setError));
            }

            // Conversion to 'Object' is done based on some reasonable default
            // conversions (Python string -> managed string, Python int -> Int32 etc.).
            if (obType == objectType)
            {
                if (Runtime.IsStringType(value))
                {
                    return(ToPrimitive(value, stringType, out result, setError));
                }

                if (Runtime.PyBool_Check(value))
                {
                    return(ToPrimitive(value, boolType, out result, setError));
                }

                if (Runtime.PyInt_Check(value))
                {
                    return(ToPrimitive(value, int32Type, out result, setError));
                }

                if (Runtime.PyLong_Check(value))
                {
                    return(ToPrimitive(value, int64Type, out result, setError));
                }

                if (Runtime.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

                // give custom codecs a chance to take over conversion of sequences
                IntPtr pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }

                if (Runtime.PySequence_Check(value))
                {
                    return(ToArray(value, typeof(object[]), out result, setError));
                }

                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            // Conversion to 'Type' is done using the same mappings as above for objects.
            if (obType == typeType)
            {
                if (value == Runtime.PyStringType)
                {
                    result = stringType;
                    return(true);
                }

                if (value == Runtime.PyBoolType)
                {
                    result = boolType;
                    return(true);
                }

                if (value == Runtime.PyIntType)
                {
                    result = int32Type;
                    return(true);
                }

                if (value == Runtime.PyLongType)
                {
                    result = int64Type;
                    return(true);
                }

                if (value == Runtime.PyFloatType)
                {
                    result = doubleType;
                    return(true);
                }

                if (value == Runtime.PyListType || value == Runtime.PyTupleType)
                {
                    result = typeof(object[]);
                    return(true);
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type");
                }

                return(false);
            }

            var underlyingType = Nullable.GetUnderlyingType(obType);

            if (underlyingType != null)
            {
                return(ToManagedValue(value, underlyingType, out result, setError, out usedImplicit));
            }

            TypeCode typeCode = Type.GetTypeCode(obType);

            if (typeCode == TypeCode.Object)
            {
                IntPtr pyType = Runtime.PyObject_TYPE(value);
                if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
                {
                    return(true);
                }
            }

            var opImplicit = obType.GetMethod("op_Implicit", new[] { obType });

            if (opImplicit != null)
            {
                if (ToManagedValue(value, opImplicit.ReturnType, out result, setError, out usedImplicit))
                {
                    opImplicit = obType.GetMethod("op_Implicit", new[] { result.GetType() });
                    if (opImplicit != null)
                    {
                        result = opImplicit.Invoke(null, new[] { result });
                    }
                    return(opImplicit != null);
                }
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
コード例 #27
0
ファイル: converter.cs プロジェクト: paloukari/pythonnet
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out object result, bool setError)
        {
            if (obType == typeof(PyObject))
            {
                Runtime.XIncref(value); // PyObject() assumes ownership
                result = new PyObject(value);
                return(true);
            }

            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            ManagedType mt = ManagedType.GetManagedObject(value);

            result = null;

            if (mt != null)
            {
                if (mt is CLRObject)
                {
                    object tmp = ((CLRObject)mt).inst;
                    if (obType.IsInstanceOfType(tmp))
                    {
                        result = tmp;
                        return(true);
                    }
                    Exceptions.SetError(Exceptions.TypeError, $"value cannot be converted to {obType}");
                    return(false);
                }
                if (mt is ClassBase)
                {
                    result = ((ClassBase)mt).type;
                    return(true);
                }
                // shouldn't happen
                return(false);
            }

            if (value == Runtime.PyNone && !obType.IsValueType)
            {
                result = null;
                return(true);
            }

            if (obType.IsGenericType && obType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                if (value == Runtime.PyNone)
                {
                    result = null;
                    return(true);
                }
                // Set type to underlying type
                obType = obType.GetGenericArguments()[0];
            }

            if (obType.IsArray)
            {
                return(ToArray(value, obType, out result, setError));
            }

            if (obType.IsEnum)
            {
                return(ToEnum(value, obType, out result, setError));
            }

            // Conversion to 'Object' is done based on some reasonable default
            // conversions (Python string -> managed string, Python int -> Int32 etc.).
            if (obType == objectType)
            {
                if (Runtime.IsStringType(value))
                {
                    return(ToPrimitive(value, stringType, out result, setError));
                }

                if (Runtime.PyBool_Check(value))
                {
                    return(ToPrimitive(value, boolType, out result, setError));
                }

                if (Runtime.PyInt_Check(value))
                {
                    return(ToPrimitive(value, int32Type, out result, setError));
                }

                if (Runtime.PyLong_Check(value))
                {
                    return(ToPrimitive(value, int64Type, out result, setError));
                }

                if (Runtime.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

                if (Runtime.Interop.PySequence_Check(value))
                {
                    return(ToArray(value, typeof(object[]), out result, setError));
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object");
                }

                return(false);
            }

            // Conversion to 'Type' is done using the same mappings as above for objects.
            if (obType == typeType)
            {
                if (value == Runtime.PyStringType)
                {
                    result = stringType;
                    return(true);
                }

                if (value == Runtime.PyBoolType)
                {
                    result = boolType;
                    return(true);
                }

                if (value == Runtime.PyIntType)
                {
                    result = int32Type;
                    return(true);
                }

                if (value == Runtime.PyLongType)
                {
                    result = int64Type;
                    return(true);
                }

                if (value == Runtime.PyFloatType)
                {
                    result = doubleType;
                    return(true);
                }

                if (value == Runtime.PyListType || value == Runtime.PyTupleType)
                {
                    result = typeof(object[]);
                    return(true);
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type");
                }

                return(false);
            }

            return(ToPrimitive(value, obType, out result, setError));
        }
コード例 #28
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;
            int          pynargs  = Runtime.PyTuple_Size(args);
            object       arg;
            var          isGeneric      = false;
            ArrayList    defaultArgList = null;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }
            Type clrtype;

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi         = mi.GetParameters();
                int             clrnargs   = pi.Length;
                var             match      = false;
                int             arrayStart = -1;
                var             outs       = 0;

                if (pynargs == clrnargs)
                {
                    match = true;
                }
                else if (pynargs < clrnargs)
                {
                    match          = true;
                    defaultArgList = new ArrayList();
                    for (int v = pynargs; v < clrnargs; v++)
                    {
                        if (pi[v].DefaultValue == DBNull.Value)
                        {
                            match = false;
                        }
                        else
                        {
                            defaultArgList.Add(pi[v].DefaultValue);
                        }
                    }
                }
                else if (pynargs > clrnargs && clrnargs > 0 &&
                         Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute)))
                {
                    // This is a `foo(params object[] bar)` style method
                    match      = true;
                    arrayStart = clrnargs - 1;
                }

                if (match)
                {
                    var margs = new object[clrnargs];

                    for (var n = 0; n < clrnargs; n++)
                    {
                        IntPtr op;
                        if (n < pynargs)
                        {
                            if (arrayStart == n)
                            {
                                // map remaining Python arguments to a tuple since
                                // the managed function accepts it - hopefully :]
                                op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
                            }
                            else
                            {
                                op = Runtime.PyTuple_GetItem(args, n);
                            }

                            // this logic below handles cases when multiple overloading methods
                            // are ambiguous, hence comparison between Python and CLR types
                            // is necessary
                            clrtype = null;
                            IntPtr pyoptype;
                            if (_methods.Length > 1)
                            {
                                pyoptype = IntPtr.Zero;
                                pyoptype = Runtime.PyObject_Type(op);
                                Exceptions.Clear();
                                if (pyoptype != IntPtr.Zero)
                                {
                                    clrtype = Converter.GetTypeByAlias(pyoptype);
                                }
                                Runtime.XDecref(pyoptype);
                            }


                            if (clrtype != null)
                            {
                                var typematch = false;
                                if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype))
                                {
                                    IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType);
                                    pyoptype = Runtime.PyObject_Type(op);
                                    Exceptions.Clear();
                                    if (pyoptype != IntPtr.Zero)
                                    {
                                        if (pytype != pyoptype)
                                        {
                                            typematch = false;
                                        }
                                        else
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                    }
                                    if (!typematch)
                                    {
                                        // this takes care of nullables
                                        var underlyingType = Nullable.GetUnderlyingType(pi[n].ParameterType);
                                        if (underlyingType == null)
                                        {
                                            underlyingType = pi[n].ParameterType;
                                        }
                                        // this takes care of enum values
                                        TypeCode argtypecode   = Type.GetTypeCode(underlyingType);
                                        TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                                        if (argtypecode == paramtypecode)
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                        // this takes care of implicit conversions
                                        var opImplicit = pi[n].ParameterType.GetMethod("op_Implicit", new[] { clrtype });
                                        if (opImplicit != null)
                                        {
                                            typematch = opImplicit.ReturnType == pi[n].ParameterType;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                    }
                                    Runtime.XDecref(pyoptype);
                                    if (!typematch)
                                    {
                                        margs = null;
                                        break;
                                    }
                                }
                                else
                                {
                                    typematch = true;
                                    clrtype   = pi[n].ParameterType;
                                }
                            }
                            else
                            {
                                clrtype = pi[n].ParameterType;
                            }

                            if (pi[n].IsOut || clrtype.IsByRef)
                            {
                                outs++;
                            }

                            if (!Converter.ToManaged(op, clrtype, out arg, false))
                            {
                                Exceptions.Clear();
                                margs = null;
                                break;
                            }
                            if (arrayStart == n)
                            {
                                // GetSlice() creates a new reference but GetItem()
                                // returns only a borrow reference.
                                Runtime.XDecref(op);
                            }
                            margs[n] = arg;
                        }
                        else
                        {
                            if (defaultArgList != null)
                            {
                                margs[n] = defaultArgList[n - pynargs];
                            }
                        }
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    object target = null;
                    if (!mi.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    return(new Binding(mi, target, margs, outs));
                }
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
コード例 #29
0
ファイル: importhook.cs プロジェクト: hua124365/pythonnet
        /// <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);
            }
        }
コード例 #30
0
        internal static bool ToManagedValue(IntPtr value, Type obType,
                                            out Object result, bool setError)
        {
            // Common case: if the Python value is a wrapped managed object
            // instance, just return the wrapped object.
            ManagedType mt = ManagedType.GetManagedObject(value);

            result = null;

            // XXX - hack to support objects wrapped in old-style classes
            // (such as exception objects).
            if (Runtime.wrap_exceptions)
            {
                if (mt == null)
                {
                    if (Runtime.PyObject_IsInstance(
                            value, Exceptions.Exception
                            ) > 0)
                    {
                        IntPtr p = Runtime.PyObject_GetAttrString(value, "_inner");
                        if (p != IntPtr.Zero)
                        {
                            // This is safe because we know that the __dict__ of
                            // value holds a reference to _inner.
                            value = p;
                            Runtime.Decref(p);
                            mt = ManagedType.GetManagedObject(value);
                        }
                    }
                    IntPtr c = Exceptions.UnwrapExceptionClass(value);
                    if ((c != IntPtr.Zero) && (c != value))
                    {
                        value = c;
                        Runtime.Decref(c);
                        mt = ManagedType.GetManagedObject(value);
                    }
                }
            }

            if (mt != null)
            {
                if (mt is CLRObject)
                {
                    object tmp = ((CLRObject)mt).inst;
                    if (obType.IsInstanceOfType(tmp))
                    {
                        result = tmp;
                        return(true);
                    }
                    string err = "value cannot be converted to {0}";
                    err = String.Format(err, obType);
                    Exceptions.SetError(Exceptions.TypeError, err);
                    return(false);
                }
                if (mt is ClassBase)
                {
                    result = ((ClassBase)mt).type;
                    return(true);
                }
                // shouldnt happen
                return(false);
            }

            if (value == Runtime.PyNone && !obType.IsValueType)
            {
                result = null;
                return(true);
            }

            if (obType.IsArray)
            {
                return(ToArray(value, obType, out result, setError));
            }

            if (obType.IsEnum)
            {
                return(ToEnum(value, obType, out result, setError));
            }

            // Conversion to 'Object' is done based on some reasonable
            // default conversions (Python string -> managed string,
            // Python int -> Int32 etc.).

            if (obType == objectType)
            {
                if (Runtime.IsStringType(value))
                {
                    return(ToPrimitive(value, stringType, out result,
                                       setError));
                }

                else if (Runtime.PyBool_Check(value))
                {
                    return(ToPrimitive(value, boolType, out result, setError));
                }

                else if (Runtime.PyInt_Check(value))
                {
                    return(ToPrimitive(value, int32Type, out result, setError));
                }

                else if (Runtime.PyLong_Check(value))
                {
                    return(ToPrimitive(value, int64Type, out result, setError));
                }

                else if (Runtime.PyFloat_Check(value))
                {
                    return(ToPrimitive(value, doubleType, out result, setError));
                }

                else if (Runtime.PySequence_Check(value))
                {
                    return(ToArray(value, typeof(object[]), out result,
                                   setError));
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError,
                                        "value cannot be converted to Object"
                                        );
                }

                return(false);
            }

            // Conversion to 'Type' is done using the same mappings as above
            // for objects.

            if (obType == typeType)
            {
                if (value == Runtime.PyStringType)
                {
                    result = stringType;
                    return(true);
                }

                else if (value == Runtime.PyBoolType)
                {
                    result = boolType;
                    return(true);
                }

                else if (value == Runtime.PyIntType)
                {
                    result = int32Type;
                    return(true);
                }

                else if (value == Runtime.PyLongType)
                {
                    result = int64Type;
                    return(true);
                }

                else if (value == Runtime.PyFloatType)
                {
                    result = doubleType;
                    return(true);
                }

                else if (value == Runtime.PyListType || value == Runtime.PyTupleType)
                {
                    result = typeof(object[]);
                    return(true);
                }

                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError,
                                        "value cannot be converted to Type"
                                        );
                }

                return(false);
            }

            return(ToPrimitive(value, obType, out result, setError));
        }