示例#1
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(BorrowedReference value, Type obType, out object?result, bool setError)
        {
            result = null;
            if (obType.IsEnum)
            {
                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "since Python.NET 3.0 int can not be converted to Enum implicitly. Use Enum(int_value)");
                }
                return(false);
            }

            TypeCode tc = Type.GetTypeCode(obType);

            switch (tc)
            {
            case TypeCode.String:
                string?st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
            {
                // Python3 always use PyLong API
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int32.MaxValue || num < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)num;
                return(true);
            }

            case TypeCode.Boolean:
                if (value == Runtime.PyTrue)
                {
                    result = true;
                    return(true);
                }
                if (value == Runtime.PyFalse)
                {
                    result = false;
                    return(true);
                }
                if (setError)
                {
                    goto type_error;
                }
                return(false);

            case TypeCode.Byte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        IntPtr bytePtr = Runtime.PyBytes_AsString(value);
                        result = (byte)Marshal.ReadByte(bytePtr);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Byte.MaxValue || num < Byte.MinValue)
                {
                    goto overflow;
                }
                result = (byte)num;
                return(true);
            }

            case TypeCode.SByte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        IntPtr bytePtr = Runtime.PyBytes_AsString(value);
                        result = (sbyte)Marshal.ReadByte(bytePtr);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > SByte.MaxValue || num < SByte.MinValue)
                {
                    goto overflow;
                }
                result = (sbyte)num;
                return(true);
            }

            case TypeCode.Char:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        IntPtr bytePtr = Runtime.PyBytes_AsString(value);
                        result = (char)Marshal.ReadByte(bytePtr);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetLength(value) == 1)
                    {
                        IntPtr unicodePtr = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff       = new Char[1];
                        Marshal.Copy(unicodePtr, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Char.MaxValue || num < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)num;
                return(true);
            }

            case TypeCode.Int16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int16.MaxValue || num < Int16.MinValue)
                {
                    goto overflow;
                }
                result = (short)num;
                return(true);
            }

            case TypeCode.Int64:
            {
                if (Runtime.Is32Bit)
                {
                    if (!Runtime.PyLong_Check(value))
                    {
                        goto type_error;
                    }
                    long?num = Runtime.PyLong_AsLongLong(value);
                    if (num is null)
                    {
                        goto convert_error;
                    }
                    result = num.Value;
                    return(true);
                }
                else
                {
                    nint num = Runtime.PyLong_AsSignedSize_t(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = (long)num;
                    return(true);
                }
            }

            case TypeCode.UInt16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt16.MaxValue || num < UInt16.MinValue)
                {
                    goto overflow;
                }
                result = (ushort)num;
                return(true);
            }

            case TypeCode.UInt32:
            {
                nuint num = Runtime.PyLong_AsUnsignedSize_t(value);
                if (num == unchecked ((nuint)(-1)) && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt32.MaxValue)
                {
                    goto overflow;
                }
                result = (uint)num;
                return(true);
            }

            case TypeCode.UInt64:
            {
                ulong?num = Runtime.PyLong_AsUnsignedLongLong(value);
                if (num is null)
                {
                    goto convert_error;
                }
                result = num.Value;
                return(true);
            }

            case TypeCode.Single:
            {
                if (!Runtime.PyFloat_Check(value) && !Runtime.PyInt_Check(value))
                {
                    goto type_error;
                }
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Single.MaxValue || num < Single.MinValue)
                {
                    if (!double.IsInfinity(num))
                    {
                        goto overflow;
                    }
                }
                result = (float)num;
                return(true);
            }

            case TypeCode.Double:
            {
                if (!Runtime.PyFloat_Check(value) && !Runtime.PyInt_Check(value))
                {
                    goto type_error;
                }
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            default:
                goto type_error;
            }

convert_error:
            if (!setError)
            {
                Exceptions.Clear();
            }
            return(false);

type_error:
            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }
            return(false);

overflow:
            // C# level overflow error
            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }
            return(false);
        }