Allow creating new .NET arrays from Python using Array[T](dim1, dim2,…) syntax by lostmsu · Pull Request #1291 · pythonnet/pythonnet
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) public static IntPtr tp_new(IntPtr tpRaw, IntPtr args, IntPtr kw) { if (kw != IntPtr.Zero) { return Exceptions.RaiseTypeError("array constructor takes no keyword arguments"); }
var tp = new BorrowedReference(tpRaw);
var self = GetManagedObject(tp) as ArrayObject; if (Runtime.PyTuple_Size(args) != 1)
long[] dimensions = new long[Runtime.PyTuple_Size(args)]; if (dimensions.Length == 0) { return Exceptions.RaiseTypeError("array expects 1 argument"); return Exceptions.RaiseTypeError("array constructor requires at least one integer argument or an object convertible to array"); } if (dimensions.Length != 1) { return CreateMultidimensional(self.type.GetElementType(), dimensions, shapeTuple: new BorrowedReference(args), pyType: tp) .DangerousMoveToPointerOrNull(); }
IntPtr op = Runtime.PyTuple_GetItem(args, 0);
// create single dimensional array if (Runtime.PyInt_Check(op)) { dimensions[0] = Runtime.PyLong_AsLongLong(op); if (dimensions[0] == -1 && Exceptions.ErrorOccurred()) { Exceptions.Clear(); } else { return NewInstance(self.type.GetElementType(), tp, dimensions) .DangerousMoveToPointerOrNull(); } } object result;
// this implements casting to Array[T] if (!Converter.ToManaged(op, self.type, out result, true)) { return IntPtr.Zero; } return CLRObject.GetInstHandle(result, tp); return CLRObject.GetInstHandle(result, tp) .DangerousGetAddress(); }
static NewReference CreateMultidimensional(Type elementType, long[] dimensions, BorrowedReference shapeTuple, BorrowedReference pyType) { for (int dimIndex = 0; dimIndex < dimensions.Length; dimIndex++) { BorrowedReference dimObj = Runtime.PyTuple_GetItem(shapeTuple, dimIndex); PythonException.ThrowIfIsNull(dimObj);
if (!Runtime.PyInt_Check(dimObj)) { Exceptions.RaiseTypeError("array constructor expects integer dimensions"); return default; }
dimensions[dimIndex] = Runtime.PyLong_AsLongLong(dimObj); if (dimensions[dimIndex] == -1 && Exceptions.ErrorOccurred()) { Exceptions.RaiseTypeError("array constructor expects integer dimensions"); return default; } }
return NewInstance(elementType, pyType, dimensions); }
static NewReference NewInstance(Type elementType, BorrowedReference arrayPyType, long[] dimensions) { object result; try { result = Array.CreateInstance(elementType, dimensions); } catch (ArgumentException badArgument) { Exceptions.SetError(Exceptions.ValueError, badArgument.Message); return default; } catch (OverflowException overflow) { Exceptions.SetError(overflow); return default; } catch (NotSupportedException notSupported) { Exceptions.SetError(notSupported); return default; } catch (OutOfMemoryException oom) { Exceptions.SetError(Exceptions.MemoryError, oom.Message); return default; } return CLRObject.GetInstHandle(result, arrayPyType); }