private PySequence_Check ( IntPtr pointer ) : bool | ||
pointer | IntPtr | |
return | bool |
static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference) { isNewReference = false; IntPtr op; // for a params method, we may have a sequence or single/multiple items // here we look to see if the item at the paramIndex is there or not // and then if it is a sequence itself. if ((pyArgCount - arrayStart) == 1) { // we only have one argument left, so we need to check it // to see if it is a sequence or a single item IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart); if (!Runtime.PyString_Check(item) && Runtime.PySequence_Check(item)) { // it's a sequence (and not a string), so we use it as the op op = item; } else { isNewReference = true; op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount); } } else { isNewReference = true; op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount); } return(op); }
static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference) { isNewReference = false; IntPtr op; // for a params method, we may have a sequence or single/multiple items // here we look to see if the item at the paramIndex is there or not // and then if it is a sequence itself. if ((pyArgCount - arrayStart) == 1) { // Ee only have one argument left, so we need to check to see if it is a sequence or a single item // We also need to check if this object is possibly a wrapped C# Enumerable Object IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart); if (!Runtime.PyString_Check(item) && (Runtime.PySequence_Check(item) || (ManagedType.GetManagedObject(item) as CLRObject)?.inst is IEnumerable)) { // it's a sequence (and not a string), so we use it as the op op = item; } else { // Its a single value that needs to be converted into the params array isNewReference = true; op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount); } } else { // Its a set of individual values, so we grab them as a tuple to be converted into the params array isNewReference = true; op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount); } return(op); }
/// <summary> /// Helper function for ToArray and ToList that creates a IList out of iterable objects /// </summary> /// <param name="value"></param> /// <param name="IterObject"></param> /// <param name="obType"></param> /// <param name="elementType"></param> /// <param name="setError"></param> /// <returns></returns> private static IList MakeList(IntPtr value, IntPtr IterObject, Type obType, Type elementType, bool setError) { IList list; try { // MakeGenericType can throw because elementType may not be a valid generic argument even though elementType[] is a valid array type. // For example, if elementType is a pointer type. // See https://docs.microsoft.com/en-us/dotnet/api/system.type.makegenerictype#System_Type_MakeGenericType_System_Type var constructedListType = typeof(List <>).MakeGenericType(elementType); bool IsSeqObj = Runtime.PySequence_Check(value); if (IsSeqObj) { var len = Runtime.PySequence_Size(value); list = (IList)Activator.CreateInstance(constructedListType, new Object[] { (int)len }); } else { // CreateInstance can throw even if MakeGenericType succeeded. // See https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance#System_Activator_CreateInstance_System_Type_ list = (IList)Activator.CreateInstance(constructedListType); } } catch (Exception e) { if (setError) { Exceptions.SetError(e); SetConversionError(value, obType); } return(null); } IntPtr item; var usedImplicit = false; while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero) { object obj; if (!Converter.ToManaged(item, elementType, out obj, setError, out usedImplicit)) { Runtime.XDecref(item); return(null); } list.Add(obj); Runtime.XDecref(item); } Runtime.XDecref(IterObject); return(list); }
/// <summary> /// Convert a Python value to a correctly typed managed array instance. /// The Python value must support the Python iterator protocol or and the /// items in the sequence must be convertible to the target array type. /// </summary> private static bool ToArray(IntPtr value, Type obType, out object result, bool setError) { Type elementType = obType.GetElementType(); result = null; bool IsSeqObj = Runtime.PySequence_Check(value); var len = IsSeqObj ? Runtime.PySequence_Size(value) : -1; IntPtr IterObject = Runtime.PyObject_GetIter(value); if (IterObject == IntPtr.Zero) { if (setError) { SetConversionError(value, obType); } return(false); } Array items; var listType = typeof(List <>); var constructedListType = listType.MakeGenericType(elementType); IList list = IsSeqObj ? (IList)Activator.CreateInstance(constructedListType, new Object[] { (int)len }) : (IList)Activator.CreateInstance(constructedListType); IntPtr item; while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero) { object obj = null; if (!Converter.ToManaged(item, elementType, out obj, true)) { Runtime.XDecref(item); return(false); } list.Add(obj); Runtime.XDecref(item); } Runtime.XDecref(IterObject); items = Array.CreateInstance(elementType, list.Count); list.CopyTo(items, 0); result = items; return(true); }
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)); }
/// <summary> /// IsSequenceType Method /// </summary> /// /// <remarks> /// Returns true if the given object implements the sequence protocol. /// </remarks> public static bool IsSequenceType(PyObject value) { return(Runtime.PySequence_Check(value.obj)); }
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) { result = ((ClassBase)mt).type; return(true); } // shouldn't happen return(false); } if (value == Runtime.PyNone && !obType.IsValueType) { result = null; return(true); } 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)); } if (Runtime.PySequence_Check(value)) { return(ToArray(value, typeof(object[]), out result, setError)); } if (setError) { Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object"); } return(false); } // 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); } return(ToPrimitive(value, obType, out result, setError)); }
internal static bool ToManagedValue(IntPtr value, Type obType, out Object result, bool 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; // XXX - hack to support objects wrapped in old-style classes // (such as exception objects). if (Runtime.wrap_exceptions) { if (mt == null) { if (Runtime.PyObject_IsInstance( value, Exceptions.Exception ) > 0) { IntPtr p = Runtime.PyObject_GetAttrString(value, "_inner"); if (p != IntPtr.Zero) { // This is safe because we know that the __dict__ of // value holds a reference to _inner. value = p; Runtime.Decref(p); mt = ManagedType.GetManagedObject(value); } } IntPtr c = Exceptions.UnwrapExceptionClass(value); if ((c != IntPtr.Zero) && (c != value)) { value = c; Runtime.Decref(c); mt = ManagedType.GetManagedObject(value); } } } if (mt != null) { if (mt is CLRObject) { object tmp = ((CLRObject)mt).inst; if (obType.IsInstanceOfType(tmp)) { result = tmp; return(true); } string err = "value cannot be converted to {0}"; err = String.Format(err, obType); Exceptions.SetError(Exceptions.TypeError, err); return(false); } if (mt is ClassBase) { result = ((ClassBase)mt).type; return(true); } // shouldnt happen return(false); } if (value == Runtime.PyNone && !obType.IsValueType) { result = null; return(true); } 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)); } else if (Runtime.PyBool_Check(value)) { return(ToPrimitive(value, boolType, out result, setError)); } else if (Runtime.PyInt_Check(value)) { return(ToPrimitive(value, int32Type, out result, setError)); } else if (Runtime.PyLong_Check(value)) { return(ToPrimitive(value, int64Type, out result, setError)); } else if (Runtime.PyFloat_Check(value)) { return(ToPrimitive(value, doubleType, out result, setError)); } else if (Runtime.PySequence_Check(value)) { return(ToArray(value, typeof(object[]), out result, setError)); } if (setError) { Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object" ); } return(false); } // Conversion to 'Type' is done using the same mappings as above // for objects. if (obType == typeType) { if (value == Runtime.PyStringType) { result = stringType; return(true); } else if (value == Runtime.PyBoolType) { result = boolType; return(true); } else if (value == Runtime.PyIntType) { result = int32Type; return(true); } else if (value == Runtime.PyLongType) { result = int64Type; return(true); } else if (value == Runtime.PyFloatType) { result = doubleType; return(true); } else 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); } return(ToPrimitive(value, obType, out result, setError)); }
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)); }
/// <summary> /// Convert a Python value to a correctly typed managed array instance. /// The Python value must support the Python iterator protocol or and the /// items in the sequence must be convertible to the target array type. /// </summary> private static bool ToArray(BorrowedReference value, Type obType, out object?result, bool setError) { Type elementType = obType.GetElementType(); result = null; using var IterObject = Runtime.PyObject_GetIter(value); if (IterObject.IsNull()) { if (setError) { SetConversionError(value, obType); } else { // PyObject_GetIter will have set an error Exceptions.Clear(); } return(false); } IList list; try { // MakeGenericType can throw because elementType may not be a valid generic argument even though elementType[] is a valid array type. // For example, if elementType is a pointer type. // See https://docs.microsoft.com/en-us/dotnet/api/system.type.makegenerictype#System_Type_MakeGenericType_System_Type var constructedListType = typeof(List <>).MakeGenericType(elementType); bool IsSeqObj = Runtime.PySequence_Check(value); object[] constructorArgs = Array.Empty <object>(); if (IsSeqObj) { var len = Runtime.PySequence_Size(value); if (len >= 0) { if (len <= int.MaxValue) { constructorArgs = new object[] { (int)len }; } } else { // for the sequences, that explicitly deny calling __len__() Exceptions.Clear(); } } // CreateInstance can throw even if MakeGenericType succeeded. // See https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance#System_Activator_CreateInstance_System_Type_ list = (IList)Activator.CreateInstance(constructedListType, args: constructorArgs); } catch (Exception e) { if (setError) { Exceptions.SetError(e); SetConversionError(value, obType); } return(false); } while (true) { using var item = Runtime.PyIter_Next(IterObject.Borrow()); if (item.IsNull()) { break; } if (!Converter.ToManaged(item.Borrow(), elementType, out var obj, setError)) { return(false); } list.Add(obj); } if (Exceptions.ErrorOccurred()) { if (!setError) { Exceptions.Clear(); } return(false); } Array items = Array.CreateInstance(elementType, list.Count); list.CopyTo(items, 0); result = items; return(true); }
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)); }
/// <summary> /// Convert a Python value to a correctly typed managed array instance. /// The Python value must support the Python iterator protocol or and the /// items in the sequence must be convertible to the target array type. /// </summary> private static bool ToArray(IntPtr value, Type obType, out object result, bool setError) { Type elementType = obType.GetElementType(); result = null; IntPtr IterObject = Runtime.PyObject_GetIter(value); if (IterObject == IntPtr.Zero) { if (setError) { SetConversionError(value, obType); } else { // PyObject_GetIter will have set an error Exceptions.Clear(); } return(false); } IList list; try { // MakeGenericType can throw because elementType may not be a valid generic argument even though elementType[] is a valid array type. // For example, if elementType is a pointer type. // See https://docs.microsoft.com/en-us/dotnet/api/system.type.makegenerictype#System_Type_MakeGenericType_System_Type var constructedListType = typeof(List <>).MakeGenericType(elementType); bool IsSeqObj = Runtime.PySequence_Check(value); if (IsSeqObj) { var len = Runtime.PySequence_Size(value); list = (IList)Activator.CreateInstance(constructedListType, new Object[] { (int)len }); } else { // CreateInstance can throw even if MakeGenericType succeeded. // See https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance#System_Activator_CreateInstance_System_Type_ list = (IList)Activator.CreateInstance(constructedListType); } } catch (Exception e) { if (setError) { Exceptions.SetError(e); SetConversionError(value, obType); } return(false); } IntPtr item; while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero) { object obj; if (!Converter.ToManaged(item, elementType, out obj, setError)) { Runtime.XDecref(item); return(false); } list.Add(obj); Runtime.XDecref(item); } Runtime.XDecref(IterObject); Array items = Array.CreateInstance(elementType, list.Count); list.CopyTo(items, 0); result = items; return(true); }