Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0e57cdd

Browse files
authored
support for BigInteger <-> PyInt (#1710)
fixes#1642 (comment)
1 parenteec30c0 commit0e57cdd

File tree

7 files changed

+119
-11
lines changed

7 files changed

+119
-11
lines changed

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
2222
- .NET collection types now implement standard Python collection interfaces from`collections.abc`.
2323
See[Mixins/collections.py](src/runtime/Mixins/collections.py).
2424
- .NET arrays implement Python buffer protocol
25+
- Python integer interoperability with`System.Numerics.BigInteger`
2526
- Python.NET will correctly resolve .NET methods, that accept`PyList`,`PyInt`,
2627
and other`PyObject` derived types when called from Python.
2728
- .NET classes, that have`__call__` method are callable from Python

‎src/embed_tests/TestConverter.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
usingSystem;
22
usingSystem.Collections.Generic;
33
usingSystem.Linq;
4+
usingSystem.Numerics;
45

56
usingNUnit.Framework;
67

@@ -131,6 +132,25 @@ public void ToNullable()
131132
Assert.AreEqual(Const,ni);
132133
}
133134

135+
[Test]
136+
publicvoidBigIntExplicit()
137+
{
138+
BigIntegerval=42;
139+
vari=newPyInt(val);
140+
varni=i.As<BigInteger>();
141+
Assert.AreEqual(val,ni);
142+
varnullable=i.As<BigInteger?>();
143+
Assert.AreEqual(val,nullable);
144+
}
145+
146+
[Test]
147+
publicvoidPyIntImplicit()
148+
{
149+
vari=newPyInt(1);
150+
varni=(PyObject)i.As<object>();
151+
Assert.AreEqual(i.rawPtr,ni.rawPtr);
152+
}
153+
134154
[Test]
135155
publicvoidToPyList()
136156
{

‎src/embed_tests/TestPyInt.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
usingSystem;
2+
usingSystem.Globalization;
3+
usingSystem.Linq;
4+
usingSystem.Numerics;
5+
26
usingNUnit.Framework;
37
usingPython.Runtime;
48

@@ -179,5 +183,35 @@ public void TestConvertToInt64()
179183
Assert.IsInstanceOf(typeof(long),a.ToInt64());
180184
Assert.AreEqual(val,a.ToInt64());
181185
}
186+
187+
[Test]
188+
publicvoidToBigInteger()
189+
{
190+
int[]simpleValues=
191+
{
192+
0,1,2,
193+
0x10,
194+
0x123,
195+
0x1234,
196+
};
197+
simpleValues=simpleValues.Concat(simpleValues.Select(v=>-v)).ToArray();
198+
199+
foreach(varvalinsimpleValues)
200+
{
201+
varpyInt=newPyInt(val);
202+
Assert.AreEqual((BigInteger)val,pyInt.ToBigInteger());
203+
}
204+
}
205+
206+
[Test]
207+
publicvoidToBigIntegerLarge()
208+
{
209+
BigIntegerval=BigInteger.Pow(2,1024)+3;
210+
varpyInt=newPyInt(val);
211+
Assert.AreEqual(val,pyInt.ToBigInteger());
212+
val=-val;
213+
pyInt=newPyInt(val);
214+
Assert.AreEqual(val,pyInt.ToBigInteger());
215+
}
182216
}
183217
}

‎src/runtime/Converter.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,14 @@ internal static bool ToManagedValue(BorrowedReference value, Type obType,
455455
}
456456
}
457457

458+
if(obType==typeof(System.Numerics.BigInteger)
459+
&&Runtime.PyInt_Check(value))
460+
{
461+
usingvarpyInt=newPyInt(value);
462+
result=pyInt.ToBigInteger();
463+
returntrue;
464+
}
465+
458466
returnToPrimitive(value,obType,outresult,setError);
459467
}
460468

‎src/runtime/PythonTypes/PyInt.cs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
usingSystem;
2+
usingSystem.Globalization;
3+
usingSystem.Numerics;
24
usingSystem.Runtime.Serialization;
35

46
namespacePython.Runtime
57
{
68
/// <summary>
7-
/// Represents a Python integer object. See the documentation at
8-
/// PY2: https://docs.python.org/2/c-api/int.html
9-
/// PY3: No equivalent
10-
/// for details.
9+
/// Represents a Python integer object.
10+
/// See the documentation at https://docs.python.org/3/c-api/long.html
1111
/// </summary>
12-
publicclassPyInt:PyNumber
12+
publicclassPyInt:PyNumber,IFormattable
1313
{
1414
internalPyInt(inStolenReferenceptr):base(ptr)
1515
{
1616
}
1717

18-
internalPyInt(BorrowedReferencereference):base(reference)
18+
internalPyInt(BorrowedReferencereference):base(reference)
1919
{
2020
if(!Runtime.PyInt_Check(reference))thrownewArgumentException("object is not an int");
2121
}
@@ -135,6 +135,8 @@ public PyInt(string value) : base(Runtime.PyLong_FromString(value, 0).StealOrThr
135135
{
136136
}
137137

138+
publicPyInt(BigIntegervalue):this(value.ToString(CultureInfo.InvariantCulture)){}
139+
138140
protectedPyInt(SerializationInfoinfo,StreamingContextcontext)
139141
:base(info,context){}
140142

@@ -198,5 +200,35 @@ public long ToInt64()
198200
}
199201
returnval.Value;
200202
}
203+
204+
publicBigIntegerToBigInteger()
205+
{
206+
usingvarpyHex=Runtime.HexCallable.Invoke(this);
207+
stringhex=pyHex.As<string>();
208+
intoffset=0;
209+
boolneg=false;
210+
if(hex[0]=='-')
211+
{
212+
offset++;
213+
neg=true;
214+
}
215+
byte[]littleEndianBytes=newbyte[(hex.Length-offset+1)/2];
216+
for(;offset<hex.Length;offset++)
217+
{
218+
intlittleEndianHexIndex=hex.Length-1-offset;
219+
intbyteIndex=littleEndianHexIndex/2;
220+
intisByteTopHalf=littleEndianHexIndex&1;
221+
intvalueShift=isByteTopHalf*4;
222+
littleEndianBytes[byteIndex]+=(byte)(Util.HexToInt(hex[offset])<<valueShift);
223+
}
224+
varresult=newBigInteger(littleEndianBytes);
225+
returnneg?-result:result;
226+
}
227+
228+
publicstringToString(stringformat,IFormatProviderformatProvider)
229+
{
230+
usingvar_=Py.GIL();
231+
returnToBigInteger().ToString(format,formatProvider);
232+
}
201233
}
202234
}

‎src/runtime/Runtime.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ internal static void Initialize(bool initSigs = false)
179179

180180
clrInterop=GetModuleLazy("clr.interop");
181181
inspect=GetModuleLazy("inspect");
182+
hexCallable=new(()=>newPyString("%x").GetAttr("__mod__"));
182183
}
183184

184185
staticvoidNewRun()
@@ -279,8 +280,9 @@ internal static void Shutdown()
279280

280281
Exceptions.Shutdown();
281282
PythonEngine.InteropConfiguration.Dispose();
282-
DisposeLazyModule(clrInterop);
283-
DisposeLazyModule(inspect);
283+
DisposeLazyObject(clrInterop);
284+
DisposeLazyObject(inspect);
285+
DisposeLazyObject(hexCallable);
284286
PyObjectConversions.Reset();
285287

286288
PyGC_Collect();
@@ -352,11 +354,11 @@ static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
352354
publicstaticboolTryCollectingGarbage(intruns)
353355
=>TryCollectingGarbage(runs,forceBreakLoops:false);
354356

355-
staticvoidDisposeLazyModule(Lazy<PyObject>module)
357+
staticvoidDisposeLazyObject(Lazy<PyObject>pyObject)
356358
{
357-
if(module.IsValueCreated)
359+
if(pyObject.IsValueCreated)
358360
{
359-
module.Value.Dispose();
361+
pyObject.Value.Dispose();
360362
}
361363
}
362364

@@ -489,8 +491,12 @@ private static void NullGCHandles(IEnumerable<IntPtr> objects)
489491

490492
privatestaticLazy<PyObject>inspect;
491493
internalstaticPyObjectInspectModule=>inspect.Value;
494+
492495
privatestaticLazy<PyObject>clrInterop;
493496
internalstaticPyObjectInteropModule=>clrInterop.Value;
497+
498+
privatestaticLazy<PyObject>hexCallable;
499+
internalstaticPyObjectHexCallable=>hexCallable.Value;
494500
#pragma warning restoreCS8618// Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
495501

496502
internalstaticBorrowedReferenceCLRMetaType=>PyCLRMetaType;

‎src/runtime/Util/Util.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ internal static string ReadStringResource(this System.Reflection.Assembly assemb
141141
returnreader.ReadToEnd();
142142
}
143143

144+
publicstaticintHexToInt(charhex)=>hexswitch
145+
{
146+
>='0' and<='9'=>hex-'0',
147+
>='a' and<='f'=>hex-'a'+10,
148+
_=>thrownewArgumentOutOfRangeException(nameof(hex)),
149+
};
150+
144151
publicstaticIEnumerator<T>GetEnumerator<T>(thisIEnumerator<T>enumerator)=>enumerator;
145152

146153
publicstaticIEnumerable<T>WhereNotNull<T>(thisIEnumerable<T?>source)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp