/// <summary> /// Shutdown Method /// </summary> /// <remarks> /// Shutdown and release resources held by the Python runtime. The /// Python runtime can no longer be used in the current process /// after calling the Shutdown method. /// </remarks> public static void Shutdown() { if (initialized) { PyScopeManager.Global.Clear(); // If the shutdown handlers trigger a domain unload, // don't call shutdown again. AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload; ExecuteShutdownHandlers(); PyObjectConversions.Reset(); initialized = false; } }
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) { var cb = (ClassBase)mt; 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.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); } 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); } } return(ToPrimitive(value, obType, out result, setError)); }
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 (Type.GetTypeCode(type) == TypeCode.Object && value.GetType() != typeof(object)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { result = encoded.Handle; 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); } } if (type.IsInterface) { var ifaceObj = (InterfaceObject)ClassManager.GetClass(type); return(ifaceObj.WrapObject(value)); } // We need to special case interface array handling to ensure we // produce the correct type. Value may be an array of some concrete // type (FooImpl[]), but we want access to go via the interface type // (IFoo[]). if (type.IsArray && type.GetElementType().IsInterface) { return(CLRObject.GetInstHandle(value, type)); } // 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 (!IsTransparentProxy(pyderived)) { return(ClassDerivedObject.ToPython(pyderived)); } } // 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); } }
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 (Type.GetTypeCode(type) == TypeCode.Object && value.GetType() != typeof(object)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { result = encoded.Handle; 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); } }
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)); }
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 (Type.GetTypeCode(type) == TypeCode.Object && value.GetType() != typeof(object)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { result = encoded.Handle; 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 (!IsTransparentProxy(pyderived)) { return(ClassDerivedObject.ToPython(pyderived)); } } // 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: if (value is TimeSpan) { var timespan = (TimeSpan)value; IntPtr timeSpanArgs = Runtime.PyTuple_New(1); Runtime.PyTuple_SetItem(timeSpanArgs, 0, Runtime.PyFloat_FromDouble(timespan.TotalDays)); var returnTimeSpan = Runtime.PyObject_CallObject(timeSpanCtor, timeSpanArgs); // clean up Runtime.XDecref(timeSpanArgs); return(returnTimeSpan); } 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); NewReference op = Runtime.PyFloat_FromString(new BorrowedReference(ps));; Runtime.XDecref(ps); return(op.DangerousMoveToPointerOrNull()); 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)); case TypeCode.Decimal: // C# decimal to python decimal has a big impact on performance // so we will use C# double and python float return(Runtime.PyFloat_FromDouble(decimal.ToDouble((decimal)value))); case TypeCode.DateTime: var datetime = (DateTime)value; var size = datetime.Kind == DateTimeKind.Unspecified ? 7 : 8; IntPtr dateTimeArgs = Runtime.PyTuple_New(size); Runtime.PyTuple_SetItem(dateTimeArgs, 0, Runtime.PyInt_FromInt32(datetime.Year)); Runtime.PyTuple_SetItem(dateTimeArgs, 1, Runtime.PyInt_FromInt32(datetime.Month)); Runtime.PyTuple_SetItem(dateTimeArgs, 2, Runtime.PyInt_FromInt32(datetime.Day)); Runtime.PyTuple_SetItem(dateTimeArgs, 3, Runtime.PyInt_FromInt32(datetime.Hour)); Runtime.PyTuple_SetItem(dateTimeArgs, 4, Runtime.PyInt_FromInt32(datetime.Minute)); Runtime.PyTuple_SetItem(dateTimeArgs, 5, Runtime.PyInt_FromInt32(datetime.Second)); // datetime.datetime 6th argument represents micro seconds var totalSeconds = datetime.TimeOfDay.TotalSeconds; var microSeconds = Convert.ToInt32((totalSeconds - Math.Truncate(totalSeconds)) * 1000000); if (microSeconds == 1000000) { microSeconds = 999999; } Runtime.PyTuple_SetItem(dateTimeArgs, 6, Runtime.PyInt_FromInt32(microSeconds)); if (size == 8) { Runtime.PyTuple_SetItem(dateTimeArgs, 7, TzInfo(datetime.Kind)); } var returnDateTime = Runtime.PyObject_CallObject(dateTimeCtor, dateTimeArgs); // clean up Runtime.XDecref(dateTimeArgs); return(returnDateTime); 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); } }
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)); }
internal static NewReference ToPython(object?value, Type type) { if (value is PyObject pyObj) { return(new NewReference(pyObj)); } // Null always converts to None in Python. if (value == null) { return(new NewReference(Runtime.PyNone)); } if (EncodableByUser(type, value)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { return(new NewReference(encoded)); } } if (type.IsInterface) { var ifaceObj = (InterfaceObject)ClassManager.GetClassImpl(type); return(ifaceObj.TryWrapObject(value)); } if (type.IsArray || type.IsEnum) { return(CLRObject.GetReference(value, type)); } // 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 (!IsTransparentProxy(pyderived)) { return(ClassDerivedObject.ToPython(pyderived)); } } // ModuleObjects are created in a way that their wrapping them as // a CLRObject fails, the ClassObject has no tpHandle. Return the // pyHandle as is, do not convert. if (value is ModuleObject modobj) { throw new NotImplementedException(); } // 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(); if (type.IsEnum) { return(CLRObject.GetReference(value, type)); } TypeCode tc = Type.GetTypeCode(type); switch (tc) { case TypeCode.Object: return(CLRObject.GetReference(value, type)); case TypeCode.String: return(Runtime.PyString_FromString((string)value)); case TypeCode.Int32: return(Runtime.PyInt_FromInt32((int)value)); case TypeCode.Boolean: if ((bool)value) { return(new NewReference(Runtime.PyTrue)); } return(new NewReference(Runtime.PyFalse)); case TypeCode.Byte: return(Runtime.PyInt_FromInt32((byte)value)); case TypeCode.Char: return(Runtime.PyUnicode_FromOrdinal((int)((char)value))); case TypeCode.Int16: return(Runtime.PyInt_FromInt32((short)value)); case TypeCode.Int64: return(Runtime.PyLong_FromLongLong((long)value)); case TypeCode.Single: return(Runtime.PyFloat_FromDouble((float)value)); case TypeCode.Double: return(Runtime.PyFloat_FromDouble((double)value)); case TypeCode.SByte: return(Runtime.PyInt_FromInt32((sbyte)value)); case TypeCode.UInt16: return(Runtime.PyInt_FromInt32((ushort)value)); case TypeCode.UInt32: return(Runtime.PyLong_FromUnsignedLongLong((uint)value)); case TypeCode.UInt64: return(Runtime.PyLong_FromUnsignedLongLong((ulong)value)); default: return(CLRObject.GetReference(value, type)); } }