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 (!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 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 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)); } }