- Notifications
You must be signed in to change notification settings - Fork750
Fix (U)IntPtr construction#1861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
1c21526
004232f
c88b1f6
65a6408
775efd5
ae5e074
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -70,22 +70,9 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo | ||
// Primitive types do not have constructors, but they look like | ||
// they do from Python. If the ClassObject represents one of the | ||
// convertible primitive types, just convert the arg directly. | ||
if (type.IsPrimitive) | ||
{ | ||
return NewPrimitive(tp, args, type); | ||
} | ||
if (type.IsAbstract) | ||
@@ -99,6 +86,11 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo | ||
return NewEnum(type, args, tp); | ||
} | ||
if (type == typeof(string)) | ||
{ | ||
return NewString(args, tp); | ||
} | ||
if (IsGenericNullable(type)) | ||
{ | ||
// Nullable<T> has special handling in .NET runtime. | ||
@@ -112,6 +104,127 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo | ||
return self.NewObjectToPython(obj, tp); | ||
} | ||
/// <summary> | ||
/// Construct a new .NET String object from Python args | ||
/// </summary> | ||
private static NewReference NewString(BorrowedReference args, BorrowedReference tp) | ||
{ | ||
if (Runtime.PyTuple_Size(args) == 1) | ||
{ | ||
BorrowedReference ob = Runtime.PyTuple_GetItem(args, 0); | ||
if (Runtime.PyString_Check(ob)) | ||
{ | ||
if (Runtime.GetManagedString(ob) is string val) | ||
return CLRObject.GetReference(val, tp); | ||
} | ||
// TODO: Initialise using constructors instead | ||
Exceptions.SetError(Exceptions.TypeError, "no constructors match given arguments"); | ||
return default; | ||
} | ||
return default; | ||
} | ||
/// <summary> | ||
/// Create a new Python object for a primitive type | ||
/// | ||
/// The primitive types are Boolean, Byte, SByte, Int16, UInt16, | ||
/// Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, | ||
/// and Single. | ||
/// | ||
/// All numeric types and Boolean can be handled by a simple | ||
/// conversion, (U)IntPtr has to be handled separately as we | ||
/// do not want to convert them automically to/from integers. | ||
/// </summary> | ||
/// <param name="type">.NET type to construct</param> | ||
/// <param name="tp">Corresponding Python type</param> | ||
/// <param name="args">Constructor arguments</param> | ||
private static NewReference NewPrimitive(BorrowedReference tp, BorrowedReference args, Type type) | ||
{ | ||
// TODO: Handle IntPtr | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. dead TODO? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. True, I'll remove it. | ||
if (Runtime.PyTuple_Size(args) != 1) | ||
{ | ||
Exceptions.SetError(Exceptions.TypeError, "no constructors match given arguments"); | ||
return default; | ||
} | ||
BorrowedReference op = Runtime.PyTuple_GetItem(args, 0); | ||
object? result = null; | ||
if (type == typeof(IntPtr)) | ||
{ | ||
if (ManagedType.GetManagedObject(op) is CLRObject clrObject) | ||
{ | ||
switch (clrObject.inst) | ||
{ | ||
case nint val: | ||
result = new IntPtr(val); | ||
break; | ||
case Int64 val: | ||
result = new IntPtr(val); | ||
break; | ||
case Int32 val: | ||
result = new IntPtr(val); | ||
break; | ||
} | ||
} | ||
else if (Runtime.PyInt_Check(op)) | ||
{ | ||
long? num = Runtime.PyLong_AsLongLong(op); | ||
if (num is long n && n >= Runtime.IntPtrMinValue && n <= Runtime.IntPtrMaxValue) | ||
{ | ||
result = new IntPtr(n); | ||
} | ||
else | ||
{ | ||
Exceptions.SetError(Exceptions.OverflowError, "value not in range for IntPtr"); | ||
return default; | ||
} | ||
} | ||
} | ||
if (type == typeof(UIntPtr)) | ||
{ | ||
if (ManagedType.GetManagedObject(op) is CLRObject clrObject) | ||
{ | ||
switch (clrObject.inst) | ||
{ | ||
case nuint val: | ||
result = new UIntPtr(val); | ||
break; | ||
case UInt64 val: | ||
result = new UIntPtr(val); | ||
break; | ||
case UInt32 val: | ||
result = new UIntPtr(val); | ||
break; | ||
} | ||
} | ||
else if (Runtime.PyInt_Check(op)) | ||
{ | ||
ulong? num = Runtime.PyLong_AsUnsignedLongLong(op); | ||
if (num is ulong n && n <= Runtime.UIntPtrMaxValue) | ||
{ | ||
result = new UIntPtr(n); | ||
} | ||
else | ||
{ | ||
Exceptions.SetError(Exceptions.OverflowError, "value not in range for UIntPtr"); | ||
return default; | ||
} | ||
} | ||
} | ||
if (result == null && !Converter.ToManaged(op, type, out result, true)) | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I think we need a test for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. What do you expect to happen? It fails to convert, this is essentially the "old" code path. I'll add the test, though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. @filmor actually, nothing specific. Just want to ensure it does not error in a weird way and the error is actually helpful. | ||
{ | ||
return default; | ||
} | ||
return CLRObject.GetReference(result!, tp); | ||
} | ||
protected virtual void SetTypeNewSlot(BorrowedReference pyType, SlotsHolder slotsHolder) | ||
{ | ||
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.tp_new, new Interop.BBB_N(tp_new_impl), slotsHolder); | ||