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)); } }
internal static IntPtr ToPython(object value, Type type) { if (value is PyObject) { IntPtr handle = ((PyObject)value).Handle; Runtime.XIncref(handle); return(handle); } IntPtr result = IntPtr.Zero; // Null always converts to None in Python. if (value == null) { result = Runtime.PyNone; Runtime.XIncref(result); return(result); } if (value is IList && !(value is INotifyPropertyChanged) && value.GetType().IsGenericType) { using (var resultlist = new PyList()) { foreach (object o in (IEnumerable)value) { using (var p = new PyObject(ToPython(o, o?.GetType()))) { resultlist.Append(p); } } Runtime.XIncref(resultlist.Handle); return(resultlist.Handle); } } // it the type is a python subclass of a managed type then return the // underlying python object rather than construct a new wrapper object. var pyderived = value as IPythonDerivedType; if (null != pyderived) { #if NETSTANDARD return(ClassDerivedObject.ToPython(pyderived)); #else // if object is remote don't do this if (!System.Runtime.Remoting.RemotingServices.IsTransparentProxy(pyderived)) { return(ClassDerivedObject.ToPython(pyderived)); } #endif } // hmm - from Python, we almost never care what the declared // type is. we'd rather have the object bound to the actual // implementing class. type = value.GetType(); TypeCode tc = Type.GetTypeCode(type); switch (tc) { case TypeCode.Object: return(CLRObject.GetInstHandle(value, type)); case TypeCode.String: return(Runtime.PyUnicode_FromString((string)value)); case TypeCode.Int32: return(Runtime.PyInt_FromInt32((int)value)); case TypeCode.Boolean: if ((bool)value) { Runtime.XIncref(Runtime.PyTrue); return(Runtime.PyTrue); } Runtime.XIncref(Runtime.PyFalse); return(Runtime.PyFalse); case TypeCode.Byte: return(Runtime.PyInt_FromInt32((int)((byte)value))); case TypeCode.Char: return(Runtime.PyUnicode_FromOrdinal((int)((char)value))); case TypeCode.Int16: return(Runtime.PyInt_FromInt32((int)((short)value))); case TypeCode.Int64: return(Runtime.PyLong_FromLongLong((long)value)); case TypeCode.Single: // return Runtime.PyFloat_FromDouble((double)((float)value)); string ss = ((float)value).ToString(nfi); IntPtr ps = Runtime.PyString_FromString(ss); IntPtr op = Runtime.PyFloat_FromString(ps, IntPtr.Zero); Runtime.XDecref(ps); return(op); case TypeCode.Double: return(Runtime.PyFloat_FromDouble((double)value)); case TypeCode.SByte: return(Runtime.PyInt_FromInt32((int)((sbyte)value))); case TypeCode.UInt16: return(Runtime.PyInt_FromInt32((int)((ushort)value))); case TypeCode.UInt32: return(Runtime.PyLong_FromUnsignedLong((uint)value)); case TypeCode.UInt64: return(Runtime.PyLong_FromUnsignedLongLong((ulong)value)); default: if (value is IEnumerable) { using (var resultlist = new PyList()) { foreach (object o in (IEnumerable)value) { using (var p = new PyObject(ToPython(o, o?.GetType()))) { resultlist.Append(p); } } Runtime.XIncref(resultlist.Handle); return(resultlist.Handle); } } result = CLRObject.GetInstHandle(value, type); return(result); } }