8000 Explicit float and int conversion for builtin types (#1904) · spsforks/pythonnet-pythonnet@0909021 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 0909021

Browse files
authored
Explicit float and int conversion for builtin types (pythonnet#1904)
1 parent 5f63c67 commit 0909021

File tree

5 files changed

+82
-0
lines changed

5 files changed

+82
-0
lines changed

src/runtime/Native/ITypeOffsets.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface ITypeOffsets
2222
int nb_true_divide { get; }
2323
int nb_and { get; }
2424
int nb_int { get; }
25+
int nb_float { get; }
2526
int nb_or { get; }
2627
int nb_xor { get; }
2728
int nb_lshift { get; }

src/runtime/Native/TypeOffset.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static partial class TypeOffset
3131
internal static int nb_or { get; private set; }
3232
internal static int nb_xor { get; private set; }
3333
internal static int nb_int { get; private set; }
34+
internal static int nb_float { get; private set; }
3435
internal static int nb_lshift { get; private set; }
3536
internal static int nb_rshift { get; private set; }
3637
internal static int nb_remainder { get; private set; }

src/runtime/Types/ClassBase.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,37 @@ static NewReference tp_call_impl(BorrowedReference ob, BorrowedReference args, B
529529
return callBinder.Invoke(ob, args, kw);
530530
}
531531

532+
static NewReference DoConvert(BorrowedReference ob)
533+
{
534+
var self = (CLRObject)GetManagedObject(ob)!;
535+
using var python = self.inst.ToPython();
536+
return python.NewReferenceOrNull();
537+
}
538+
539+
static NewReference DoConvertInt(BorrowedReference ob)
540+
{
541+
var self = (CLRObject)GetManagedObject(ob)!;
542+
return Runtime.PyLong_FromLongLong(Convert.ToInt64(self.inst));
543+
}
544+
545+
static NewReference DoConvertUInt(BorrowedReference ob)
546+
{
547+
var self = (CLRObject)GetManagedObject(ob)!;
548+
return Runtime.PyLong_FromUnsignedLongLong(Convert.ToUInt64(self.inst));
549+
}
550+
551+
static NewReference DoConvertBooleanInt(BorrowedReference ob)
552+
{
553+
var self = (CLRObject)GetManagedObject(ob)!;
554+
return Runtime.PyInt_FromInt32((bool)self.inst ? 1 : 0);
555+
}
556+
557+
static NewReference DoConvertFloat(BorrowedReference ob)
558+
{
559+
var self = (CLRObject)GetManagedObject(ob)!;
560+
return Runtime.PyFloat_FromDouble(Convert.ToDouble(self.inst));
561+
}
562+
532563
static IEnumerable<MethodInfo> GetCallImplementations(Type type)
533564
=> type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
534565
.Where(m => m.Name == "__call__");
@@ -564,6 +595,29 @@ public virtual void InitializeSlots(BorrowedReference pyType, SlotsHolder slotsH
564595
{
565596
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.mp_length, new Interop.B_P(MpLengthSlot.impl), slotsHolder);
566597
}
598+
599+
switch (Type.GetTypeCode(type.Value))
600+
{
601+
case TypeCode.Boolean:
602+
case TypeCode.SByte:
603+
case TypeCode.Int16:
604+
case TypeCode.Int32:
605+
case TypeCode.Int64:
606+
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvertInt), slotsHolder);
607+
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertFloat), slotsHolder);
608+
break;
609+
case TypeCode.Byte:
610+
case TypeCode.UInt16:
611+
case TypeCode.UInt32:
612+
case TypeCode.UInt64:
613+
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_int, new Interop.B_N(DoConvertUInt), slotsHolder);
614+
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertFloat), slotsHolder);
615+
break;
616+
case TypeCode.Double:
617+
case TypeCode.Single:
618+
TypeManager.InitializeSlotIfEmpty(pyType, TypeOffset.nb_float, new Interop.B_N(DoConvertFloat), slotsHolder);
619+
break;
620+
}
567621
}
568622

569623
public virtual bool HasCustomNew() => this.GetType().GetMethod("tp_new") is not null;

src/runtime/Types/OperatorMethod.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static OperatorMethod()
5353
["op_UnaryPlus"] = new SlotDefinition("__pos__", TypeOffset.nb_positive),
5454

5555
["__int__"] = new SlotDefinition("__int__", TypeOffset.nb_int),
56+
["__float__"] = new SlotDefinition("__float__", TypeOffset.nb_float),
5657
};
5758
ComparisonOpMap = new Dictionary<string, string>
5859
{

tests/test_conversion.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,3 +720,28 @@ def test_intptr_construction():
720720
with pytest.raises(OverflowError):
721721
UIntPtr(v)
722722

723+
def test_explicit_conversion():
724+
from System import (
725+
Int64, UInt64, Int32, UInt32, Int16, UInt16, Byte, SByte, Boolean
726+
)
727+
from System import Double, Single
728+
729+
assert int(Boolean(False)) == 0
730+
assert int(Boolean(True)) == 1
731+
732+
for t in [UInt64, UInt32, UInt16, Byte]:
733+
assert int(t(127)) == 127
734+
assert float(t(127)) == 127.0
735+
736+
for t in [Int64, Int32, Int16, SByte]:
737+
assert int(t(127)) == 127
738+
assert int(t(-127)) == -127
739+
assert float(t(127)) == 127.0
740+
assert float(t(-127)) == -127.0
741+
742+
assert int(Int64.MaxValue) == 2**63 - 1
743+
assert int(Int64.MinValue) == -2**63
744+
assert int(UInt64.MaxValue) == 2**64 - 1
745+
746+
for t in [Single, Double]:
747+
assert float(t(0.125)) == 0.125

0 commit comments

Comments
 (0)
0