/// <summary> /// GetEnumerator Method /// </summary> /// <remarks> /// Return a new PyIter object for the object. This allows any iterable /// python object to be iterated over in C#. A PythonException will be /// raised if the object is not iterable. /// </remarks> public IEnumerator GetEnumerator() { return(PyIter.GetIter(this)); }
/// <summary> /// GetEnumerator Method /// </summary> /// <remarks> /// Return a new PyIter object for the object. This allows any iterable /// python object to be iterated over in C#. A PythonException will be /// raised if the object is not iterable. /// </remarks> public IEnumerator <PyObject> GetEnumerator() { return(PyIter.GetIter(this)); }
/// <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 (var pyArgTypes = PyIter.GetIter(func.GetAttr("_clr_arg_types_"))) { var returnType = pyReturnType.AsManagedObject(typeof(Type)) as Type; if (returnType == null) { returnType = typeof(void); } 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); #pragma warning disable CS0618 // PythonDerivedType is for internal use only if (returnType == typeof(void)) { il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethodVoid")); } else { il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeMethod").MakeGenericMethod(returnType)); } #pragma warning restore CS0618 // PythonDerivedType is for internal use only il.Emit(OpCodes.Ret); } }