Example #1
0
        public PythonException()
        {
            IntPtr gs = PythonEngine.AcquireLock();

            Runtime.PyErr_Fetch(ref _pyType, ref _pyValue, ref _pyTB);
            if (_pyType != IntPtr.Zero && _pyValue != IntPtr.Zero)
            {
                string type;
                string message;
                Runtime.XIncref(_pyType);
                using (var pyType = new PyObject(_pyType))
                    using (PyObject pyTypeName = pyType.GetAttr("__name__")) {
                        type = pyTypeName.ToString();
                    }

                _pythonTypeName = type;

                Runtime.XIncref(_pyValue);
                using (var pyValue = new PyObject(_pyValue)) {
                    message = pyValue.ToString();
                }
                _message = type + " : " + message;
            }
            if (_pyTB != IntPtr.Zero)
            {
                using (PyObject tb_module = PythonEngine.ImportModule("traceback")) {
                    Runtime.XIncref(_pyTB);
                    using (var pyTB = new PyObject(_pyTB)) {
                        _tb = tb_module.InvokeMethod("format_tb", pyTB).ToString();
                    }
                }
            }
            PythonEngine.ReleaseLock(gs);
        }
Example #2
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);
        }
Example #3
0
 /// <summary>
 /// Import Method
 /// </summary>
 /// <remarks>
 /// The 'import .. as ..' statement in Python.
 /// Import a module as a variable into the scope.
 /// </remarks>
 public void Import(PyObject module, string asname = null)
 {
     if (String.IsNullOrEmpty(asname))
     {
         asname = module.GetAttr("__name__").As <string>();
     }
     Set(asname, module);
 }
Example #4
0
        public static T InvokeGetProperty <T>(IPythonDerivedType obj, string propertyName)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            if (null == self)
            {
                throw new NullReferenceException("Instance must be specified when getting a property");
            }

            IntPtr gs = Runtime.PyGILState_Ensure();

            try {
                Runtime.XIncref(self.pyHandle);
                using (var pyself = new PyObject(self.pyHandle))
                    using (PyObject pyvalue = pyself.GetAttr(propertyName)) {
                        return((T)pyvalue.AsManagedObject(typeof(T)));
                    }
            }
            finally {
                Runtime.PyGILState_Release(gs);
            }
        }
Example #5
0
        /// <summary>
        /// Python properties may have the following function attributes set to control how they're exposed:
        /// - _clr_property_type_     - property type (required)
        /// </summary>
        /// <param name="propertyName">Property name to add to the type</param>
        /// <param name="func">Python property object</param>
        /// <param name="typeBuilder">TypeBuilder for the new type the method/property is to be added to</param>
        private static void AddPythonProperty(string propertyName, PyObject func, TypeBuilder typeBuilder)
        {
            // add the method to call back into python
            MethodAttributes methodAttribs = MethodAttributes.Public |
                                             MethodAttributes.Virtual |
                                             MethodAttributes.ReuseSlot |
                                             MethodAttributes.HideBySig |
                                             MethodAttributes.SpecialName;

            using (PyObject pyPropertyType = func.GetAttr("_clr_property_type_")) {
                var propertyType = pyPropertyType.AsManagedObject(typeof(Type)) as Type;
                if (propertyType == null)
                {
                    throw new ArgumentException("_clr_property_type must be a CLR type");
                }

                PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName,
                                                                             PropertyAttributes.None,
                                                                             propertyType,
                                                                             null);

                if (func.HasAttr("fget"))
                {
                    using (PyObject pyfget = func.GetAttr("fget")) {
                        if (pyfget.IsTrue())
                        {
                            MethodBuilder methodBuilder = typeBuilder.DefineMethod("get_" + propertyName,
                                                                                   methodAttribs,
                                                                                   propertyType,
                                                                                   null);

                            ILGenerator il = methodBuilder.GetILGenerator();
                            il.Emit(OpCodes.Ldarg_0);
                            il.Emit(OpCodes.Ldstr, propertyName);
                            il.Emit(OpCodes.Call,
                                    typeof(PythonDerivedType).GetMethod("InvokeGetProperty").MakeGenericMethod(propertyType));
                            il.Emit(OpCodes.Ret);

                            propertyBuilder.SetGetMethod(methodBuilder);
                        }
                    }
                }

                if (func.HasAttr("fset"))
                {
                    using (PyObject pyset = func.GetAttr("fset")) {
                        if (pyset.IsTrue())
                        {
                            MethodBuilder methodBuilder = typeBuilder.DefineMethod("set_" + propertyName,
                                                                                   methodAttribs,
                                                                                   null,
                                                                                   new[] { propertyType });

                            ILGenerator il = methodBuilder.GetILGenerator();
                            il.Emit(OpCodes.Ldarg_0);
                            il.Emit(OpCodes.Ldstr, propertyName);
                            il.Emit(OpCodes.Ldarg_1);
                            il.Emit(OpCodes.Call,
                                    typeof(PythonDerivedType).GetMethod("InvokeSetProperty").MakeGenericMethod(propertyType));
                            il.Emit(OpCodes.Ret);

                            propertyBuilder.SetSetMethod(methodBuilder);
                        }
                    }
                }
            }
        }
Example #6
0
        /// <summary>
        /// Python method may have the following function attributes set to control how they're exposed:
        /// - _clr_return_type_    - method return type (required)
        /// - _clr_arg_types_      - list of method argument types (required)
        /// - _clr_method_name_    - method name, if different from the python method name (optional)
        /// </summary>
        /// <param name="methodName">Method name to add to the type</param>
        /// <param name="func">Python callable object</param>
        /// <param name="typeBuilder">TypeBuilder for the new type the method/property is to be added to</param>
        private static void AddPythonMethod(string methodName, PyObject func, TypeBuilder typeBuilder)
        {
            if (func.HasAttr("_clr_method_name_"))
            {
                using (PyObject pyMethodName = func.GetAttr("_clr_method_name_")) {
                    methodName = pyMethodName.ToString();
                }
            }

            using (PyObject pyReturnType = func.GetAttr("_clr_return_type_"))
                using (PyObject pyArgTypes = func.GetAttr("_clr_arg_types_")) {
                    var returnType = pyReturnType.AsManagedObject(typeof(Type)) as Type;
                    if (returnType == null)
                    {
                        returnType = typeof(void);
                    }

                    if (!pyArgTypes.IsIterable())
                    {
                        throw new ArgumentException("_clr_arg_types_ must be a list or tuple of CLR types");
                    }

                    var argTypes = new List <Type>();
                    foreach (PyObject pyArgType in pyArgTypes)
                    {
                        var argType = pyArgType.AsManagedObject(typeof(Type)) as Type;
                        if (argType == null)
                        {
                            throw new ArgumentException("_clr_arg_types_ must be a list or tuple of CLR types");
                        }
                        argTypes.Add(argType);
                    }

                    // add the method to call back into python
                    MethodAttributes methodAttribs = MethodAttributes.Public |
                                                     MethodAttributes.Virtual |
                                                     MethodAttributes.ReuseSlot |
                                                     MethodAttributes.HideBySig;

                    MethodBuilder methodBuilder = typeBuilder.DefineMethod(methodName,
                                                                           methodAttribs,
                                                                           returnType,
                                                                           argTypes.ToArray());

                    ILGenerator il = methodBuilder.GetILGenerator();
                    il.DeclareLocal(typeof(object[]));
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldstr, methodName);
                    il.Emit(OpCodes.Ldnull); // don't fall back to the base type's method
                    il.Emit(OpCodes.Ldc_I4, argTypes.Count);
                    il.Emit(OpCodes.Newarr, typeof(object));
                    il.Emit(OpCodes.Stloc_0);
                    for (var i = 0; i < argTypes.Count; ++i)
                    {
                        il.Emit(OpCodes.Ldloc_0);
                        il.Emit(OpCodes.Ldc_I4, i);
                        il.Emit(OpCodes.Ldarg, i + 1);
                        if (argTypes[i].IsValueType)
                        {
                            il.Emit(OpCodes.Box, argTypes[i]);
                        }
                        il.Emit(OpCodes.Stelem, typeof(object));
                    }
                    il.Emit(OpCodes.Ldloc_0);
                    if (returnType == typeof(void))
                    {
                        il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethodVoid"));
                    }
                    else
                    {
                        il.Emit(OpCodes.Call,
                                typeof(PythonDerivedType).GetMethod("InvokeMethod").MakeGenericMethod(returnType));
                    }
                    il.Emit(OpCodes.Ret);
                }
        }