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
This repository was archived by the owner on Jul 22, 2023. It is now read-only.
/pythonnetPublic archive
forked frompythonnet/pythonnet

Commit770fc01

Browse files
authored
Safe pointers (pythonnet#1043)
* NewReference type and an example usage* BorrowedReference + example, that exposes dangerous pattern* make BorrowedReference readonly ref struct* BorrowedReference.Pointer is a private readonly field* renamed NewReference.ToPyObject to MoveToPyObject* removed public property Pointer from NewReference and replaced with DangerousGetAddress
1 parent4271e57 commit770fc01

9 files changed

+97
-10
lines changed

‎src/runtime/BorrowedReference.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespacePython.Runtime
2+
{
3+
usingSystem;
4+
/// <summary>
5+
/// Represents a reference to a Python object, that is being lent, and
6+
/// can only be safely used until execution returns to the caller.
7+
/// </summary>
8+
readonlyrefstructBorrowedReference
9+
{
10+
readonlyIntPtrpointer;
11+
publicboolIsNull=>this.pointer==IntPtr.Zero;
12+
13+
/// <summary>Gets a raw pointer to the Python object</summary>
14+
publicIntPtrDangerousGetAddress()
15+
=>this.IsNull?thrownewNullReferenceException():this.pointer;
16+
17+
BorrowedReference(IntPtrpointer)
18+
{
19+
this.pointer=pointer;
20+
}
21+
}
22+
}

‎src/runtime/NewReference.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
namespacePython.Runtime
2+
{
3+
usingSystem;
4+
/// <summary>
5+
/// Represents a reference to a Python object, that is tracked by Python's reference counting.
6+
/// </summary>
7+
[NonCopyable]
8+
refstructNewReference
9+
{
10+
IntPtrpointer;
11+
publicboolIsNull=>this.pointer==IntPtr.Zero;
12+
13+
/// <summary>Gets a raw pointer to the Python object</summary>
14+
publicIntPtrDangerousGetAddress()
15+
=>this.IsNull?thrownewNullReferenceException():this.pointer;
16+
17+
/// <summary>
18+
/// Returns <see cref="PyObject"/> wrapper around this reference, which now owns
19+
/// the pointer. Sets the original reference to <c>null</c>, as it no longer owns it.
20+
/// </summary>
21+
publicPyObjectMoveToPyObject()
22+
{
23+
if(this.IsNull)thrownewNullReferenceException();
24+
25+
varresult=newPyObject(this.pointer);
26+
this.pointer=IntPtr.Zero;
27+
returnresult;
28+
}
29+
/// <summary>
30+
/// Removes this reference to a Python object, and sets it to <c>null</c>.
31+
/// </summary>
32+
publicvoidDispose()
33+
{
34+
if(!this.IsNull)
35+
Runtime.XDecref(this.pointer);
36+
this.pointer=IntPtr.Zero;
37+
}
38+
}
39+
}

‎src/runtime/NonCopyableAttribute.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespacePython.Runtime
2+
{
3+
usingSystem;
4+
[AttributeUsage(AttributeTargets.Struct)]
5+
classNonCopyableAttribute:Attribute{}
6+
}

‎src/runtime/Python.Runtime.15.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@
129129
<PackageReferenceInclude="Microsoft.TargetingPack.NETFramework.v4.5"Version="1.0.1"ExcludeAssets="All"PrivateAssets="All" />
130130
</ItemGroup>
131131

132+
<ItemGroup>
133+
<PackageReferenceInclude="NonCopyableAnalyzer"Version="0.5.1">
134+
<PrivateAssets>all</PrivateAssets>
135+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
136+
</PackageReference>
137+
</ItemGroup>
138+
132139
<ImportProject="Sdk.targets"Sdk="Microsoft.NET.Sdk" />
133140

134141
<PropertyGroup>

‎src/runtime/Python.Runtime.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
</Compile>
8484
<CompileInclude="arrayobject.cs" />
8585
<CompileInclude="assemblymanager.cs" />
86+
<CompileInclude="BorrowedReference.cs" />
8687
<CompileInclude="classderived.cs" />
8788
<CompileInclude="classbase.cs" />
8889
<CompileInclude="classmanager.cs" />
@@ -119,6 +120,8 @@
119120
<CompileInclude="moduleobject.cs" />
120121
<CompileInclude="modulepropertyobject.cs" />
121122
<CompileInclude="nativecall.cs" />
123+
<CompileInclude="NewReference.cs" />
124+
<CompileInclude="NonCopyableAttribute.cs" />
122125
<CompileInclude="overload.cs" />
123126
<CompileInclude="propertyobject.cs" />
124127
<CompileInclude="pyansistring.cs" />

‎src/runtime/assemblymanager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ internal static void UpdatePath()
145145
probed.Clear();
146146
for(vari=0;i<count;i++)
147147
{
148-
IntPtritem=Runtime.PyList_GetItem(list,i);
148+
BorrowedReferenceitem=Runtime.PyList_GetItem(list,i);
149149
stringpath=Runtime.GetManagedString(item);
150150
if(path!=null)
151151
{
@@ -492,4 +492,4 @@ internal static Type[] GetTypes(Assembly a)
492492
}
493493
}
494494
}
495-
}
495+
}

‎src/runtime/methodbinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
292292
for(inti=0;i<pynkwargs;++i)
293293
{
294294
varkeyStr=Runtime.GetManagedString(Runtime.PyList_GetItem(keylist,i));
295-
kwargDict[keyStr]=Runtime.PyList_GetItem(valueList,i);
295+
kwargDict[keyStr]=Runtime.PyList_GetItem(valueList,i).DangerousGetAddress();
296296
}
297297
Runtime.XDecref(keylist);
298298
Runtime.XDecref(valueList);

‎src/runtime/pydict.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,20 @@ public PyObject Values()
139139
/// </remarks>
140140
publicPyObjectItems()
141141
{
142-
IntPtritems=Runtime.PyDict_Items(obj);
143-
if(items==IntPtr.Zero)
142+
varitems=Runtime.PyDict_Items(this.obj);
143+
try
144144
{
145-
thrownewPythonException();
145+
if(items.IsNull)
146+
{
147+
thrownewPythonException();
148+
}
149+
150+
returnitems.MoveToPyObject();
151+
}
152+
finally
153+
{
154+
items.Dispose();
146155
}
147-
returnnewPyObject(items);
148156
}
149157

150158

‎src/runtime/runtime.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,8 @@ internal static IntPtr PyUnicode_FromString(string s)
15091509
return PyUnicode_FromUnicode(s, s.Length);
15101510
}
15111511

1512+
internalstaticstring GetManagedString(in BorrowedReference borrowedReference)
1513+
=> GetManagedString(borrowedReference.DangerousGetAddress());
15121514
/// <summary>
15131515
/// Function to access the internal PyUnicode/PyString object and
15141516
/// convert it to a managed string with the correct encoding.
@@ -1591,7 +1593,7 @@ internal static bool PyDict_Check(IntPtr ob)
15911593
internalstaticextern IntPtr PyDict_Values(IntPtr pointer);
15921594

15931595
[DllImport(_PythonDll, CallingConvention= CallingConvention.Cdecl)]
1594-
internalstaticexternIntPtr PyDict_Items(IntPtr pointer);
1596+
internalstaticexternNewReference PyDict_Items(IntPtr pointer);
15951597

15961598
[DllImport(_PythonDll, CallingConvention= CallingConvention.Cdecl)]
15971599
internalstaticextern IntPtr PyDict_Copy(IntPtr pointer);
@@ -1631,13 +1633,13 @@ internal static IntPtr PyList_New(long size)
16311633
[DllImport(_PythonDll, CallingConvention= CallingConvention.Cdecl)]
16321634
internalstaticextern IntPtr PyList_AsTuple(IntPtr pointer);
16331635

1634-
internalstaticIntPtr PyList_GetItem(IntPtr pointer,long index)
1636+
internalstaticBorrowedReference PyList_GetItem(IntPtr pointer,long index)
16351637
{
16361638
return PyList_GetItem(pointer,new IntPtr(index));
16371639
}
16381640

16391641
[DllImport(_PythonDll, CallingConvention= CallingConvention.Cdecl)]
1640-
privatestaticexternIntPtr PyList_GetItem(IntPtr pointer, IntPtr index);
1642+
privatestaticexternBorrowedReference PyList_GetItem(IntPtr pointer, IntPtr index);
16411643

16421644
internalstaticint PyList_SetItem(IntPtr pointer,long index, IntPtr value)
16431645
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp