Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b7eeb06

Browse files
authored
Merge branch 'master' into PR/PyArgConverter
2 parents 16c1534 + 3b938a5 commit b7eeb06

22 files changed

+606
-151
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ dotnet_sort_system_directives_first = true
2525
dotnet_separate_import_directive_groups = true
2626

2727
[*.cs]
28-
csharp_new_line_before_open_brace = true
28+
csharp_new_line_before_open_brace = all
2929
csharp_new_line_before_else = true
3030
csharp_new_line_before_catch = true
3131
csharp_new_line_before_finally = true

AUTHORS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
## Contributors
1414

15+
- Alex Earl ([@slide](https://github.com/slide))
1516
- Alex Helms ([@alexhelms](https://github.com/alexhelms))
1617
- Alexandre Catarino([@AlexCatarino](https://github.com/AlexCatarino))
1718
- Arvid JB ([@ArvidJB](https://github.com/ArvidJB))
@@ -34,6 +35,7 @@
3435
- Ivan Cronyn ([@cronan](https://github.com/cronan))
3536
- Jan Krivanek ([@jakrivan](https://github.com/jakrivan))
3637
- Jeff Reback ([@jreback](https://github.com/jreback))
38+
- Jeff Robbins ([@jeff17robbins](https://github.com/jeff17robbins))
3739
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
3840
- Joe Lidbetter ([@jmlidbetter](https://github.com/jmlidbetter))
3941
- Joe Savage ([@s4v4g3](https://github.com/s4v4g3))

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1313
- Added `IPyArgumentConverter` interface and `PyArgConverter` attribute, that control custom argument marshaling from Python to .NET (#835)
1414
- Added function that sets Py_NoSiteFlag to 1.
1515
- Added support for Jetson Nano.
16+
- Added support for __len__ for .NET classes that implement ICollection
1617

1718
### Changed
1819

src/runtime/Python.Runtime.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
<Compile Include="Util.cs" />
145145
<Compile Include="platform\Types.cs" />
146146
<Compile Include="platform\LibraryLoader.cs" />
147+
<Compile Include="slots\mp_length.cs" />
147148
</ItemGroup>
148149
<ItemGroup Condition=" '$(PythonInteropFile)' != '' ">
149150
<Compile Include="$(PythonInteropFile)" />

src/runtime/arrayobject.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,5 @@ public static int sq_contains(IntPtr ob, IntPtr v)
244244

245245
return 0;
246246
}
247-
248-
249-
/// <summary>
250-
/// Implements __len__ for array types.
251-
/// </summary>
252-
public static int mp_length(IntPtr ob)
253-
{
254-
var self = (CLRObject)GetManagedObject(ob);
255-
var items = self.inst as Array;
256-
return items.Length;
257-
}
258247
}
259248
}

src/runtime/extensiontype.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public ExtensionType()
3838

3939
Runtime.PyObject_GC_UnTrack(py);
4040

41+
// Steals a ref to tpHandle.
4142
tpHandle = tp;
4243
pyHandle = py;
4344
gcHandle = gc;
@@ -50,7 +51,7 @@ public ExtensionType()
5051
public static void FinalizeObject(ManagedType self)
5152
{
5253
Runtime.PyObject_GC_Del(self.pyHandle);
53-
Runtime.XDecref(self.tpHandle);
54+
// Not necessary for decref of `tpHandle`.
5455
self.gcHandle.Free();
5556
}
5657

src/runtime/importhook.cs

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,17 @@ internal static void InitializeModuleDef()
2323
module_def = ModuleDefOffset.AllocModuleDef("clr");
2424
}
2525
}
26-
#endif
2726

28-
/// <summary>
29-
/// Get a <i>New reference</i> to the builtins module.
30-
/// </summary>
31-
static IntPtr GetNewRefToBuiltins()
27+
internal static void ReleaseModuleDef()
3228
{
33-
if (Runtime.IsPython3)
34-
{
35-
return Runtime.PyImport_ImportModule("builtins");
36-
}
37-
else
29+
if (module_def == IntPtr.Zero)
3830
{
39-
// dict is a borrowed ref, no need to decref
40-
IntPtr dict = Runtime.PyImport_GetModuleDict();
41-
42-
// GetItemString is a borrowed ref; incref to get a new ref
43-
IntPtr builtins = Runtime.PyDict_GetItemString(dict, "__builtin__");
44-
Runtime.XIncref(builtins);
45-
return builtins;
31+
return;
4632
}
33+
ModuleDefOffset.FreeModuleDef(module_def);
34+
module_def = IntPtr.Zero;
4735
}
36+
#endif
4837

4938
/// <summary>
5039
/// Initialize just the __import__ hook itself.
@@ -54,11 +43,14 @@ static void InitImport()
5443
// We replace the built-in Python __import__ with our own: first
5544
// look in CLR modules, then if we don't find any call the default
5645
// Python __import__.
57-
IntPtr builtins = GetNewRefToBuiltins();
46+
IntPtr builtins = Runtime.GetBuiltins();
5847
py_import = Runtime.PyObject_GetAttrString(builtins, "__import__");
48+
PythonException.ThrowIfIsNull(py_import);
49+
5950
hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc");
60-
Runtime.PyObject_SetAttrString(builtins, "__import__", hook.ptr);
61-
Runtime.XDecref(hook.ptr);
51+
int res = Runtime.PyObject_SetAttrString(builtins, "__import__", hook.ptr);
52+
PythonException.ThrowIfIsNotZero(res);
53+
6254
Runtime.XDecref(builtins);
6355
}
6456

@@ -67,12 +59,16 @@ static void InitImport()
6759
/// </summary>
6860
static void RestoreImport()
6961
{
70-
IntPtr builtins = GetNewRefToBuiltins();
62+
IntPtr builtins = Runtime.GetBuiltins();
7163

72-
Runtime.PyObject_SetAttrString(builtins, "__import__", py_import);
64+
int res = Runtime.PyObject_SetAttrString(builtins, "__import__", py_import);
65+
PythonException.ThrowIfIsNotZero(res);
7366
Runtime.XDecref(py_import);
7467
py_import = IntPtr.Zero;
7568

69+
hook.Release();
70+
hook = null;
71+
7672
Runtime.XDecref(builtins);
7773
}
7874

@@ -112,13 +108,26 @@ internal static void Initialize()
112108
/// </summary>
113109
internal static void Shutdown()
114110
{
115-
if (Runtime.Py_IsInitialized() != 0)
111+
if (Runtime.Py_IsInitialized() == 0)
116112
{
117-
RestoreImport();
113+
return;
114+
}
115+
116+
RestoreImport();
118117

119-
Runtime.XDecref(py_clr_module);
120-
Runtime.XDecref(root.pyHandle);
118+
bool shouldFreeDef = Runtime.Refcount(py_clr_module) == 1;
119+
Runtime.XDecref(py_clr_module);
120+
py_clr_module = IntPtr.Zero;
121+
#if PYTHON3
122+
if (shouldFreeDef)
123+
{
124+
ReleaseModuleDef();
121125
}
126+
#endif
127+
128+
Runtime.XDecref(root.pyHandle);
129+
root = null;
130+
CLRModule.Reset();
122131
}
123132

124133
/// <summary>

src/runtime/interop.cs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Runtime.InteropServices;
55
using System.Reflection;
66
using System.Text;
7+
using System.Collections.Generic;
78

89
namespace Python.Runtime
910
{
@@ -227,7 +228,7 @@ public static IntPtr AllocModuleDef(string modulename)
227228
byte[] ascii = Encoding.ASCII.GetBytes(modulename);
228229
int size = name + ascii.Length + 1;
229230
IntPtr ptr = Marshal.AllocHGlobal(size);
230-
for (int i = 0; i < m_free; i += IntPtr.Size)
231+
for (int i = 0; i <= m_free; i += IntPtr.Size)
231232
Marshal.WriteIntPtr(ptr, i, IntPtr.Zero);
232233
Marshal.Copy(ascii, 0, (IntPtr)(ptr + name), ascii.Length);
233234
Marshal.WriteIntPtr(ptr, m_name, (IntPtr)(ptr + name));
@@ -334,7 +335,7 @@ internal class TypeFlags
334335

335336
internal class Interop
336337
{
337-
private static ArrayList keepAlive;
338+
private static List<ThunkInfo> keepAlive;
338339
private static Hashtable pmap;
339340

340341
static Interop()
@@ -351,8 +352,7 @@ static Interop()
351352
p[item.Name] = item;
352353
}
353354

354-
keepAlive = new ArrayList();
355-
Marshal.AllocHGlobal(IntPtr.Size);
355+
keepAlive = new List<ThunkInfo>();
356356
pmap = new Hashtable();
357357

358358
pmap["tp_dealloc"] = p["DestructorFunc"];
@@ -449,26 +449,23 @@ internal static Type GetPrototype(string name)
449449
return pmap[name] as Type;
450450
}
451451

452-
internal static IntPtr GetThunk(MethodInfo method, string funcType = null)
452+
internal static ThunkInfo GetThunk(MethodInfo method, string funcType = null)
453453
{
454454
Type dt;
455455
if (funcType != null)
456456
dt = typeof(Interop).GetNestedType(funcType) as Type;
457457
else
458458
dt = GetPrototype(method.Name);
459459

460-
if (dt != null)
460+
if (dt == null)
461461
{
462-
IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size);
463-
Delegate d = Delegate.CreateDelegate(dt, method);
464-
Thunk cb = new Thunk(d);
465-
Marshal.StructureToPtr(cb, tmp, false);
466-
IntPtr fp = Marshal.ReadIntPtr(tmp, 0);
467-
Marshal.FreeHGlobal(tmp);
468-
keepAlive.Add(d);
469-
return fp;
462+
return ThunkInfo.Empty;
470463
}
471-
return IntPtr.Zero;
464+
Delegate d = Delegate.CreateDelegate(dt, method);
465+
var info = new ThunkInfo(d);
466+
// TODO: remove keepAlive when #958 merged, let the lifecycle of ThunkInfo transfer to caller.
467+
keepAlive.Add(info);
468+
return info;
472469
}
473470

474471
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@@ -522,4 +519,22 @@ public Thunk(Delegate d)
522519
fn = d;
523520
}
524521
}
522+
523+
internal class ThunkInfo
524+
{
525+
public readonly Delegate Target;
526+
public readonly IntPtr Address;
527+
528+
public static readonly ThunkInfo Empty = new ThunkInfo(null);
529+
530+
public ThunkInfo(Delegate target)
531+
{
532+
if (target == null)
533+
{
534+
return;
535+
}
536+
Target = target;
537+
Address = Marshal.GetFunctionPointerForDelegate(target);
538+
}
539+
}
525540
}

src/runtime/interop38.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
// Auto-generated by geninterop.py.
3-
// DO NOT MODIFIY BY HAND.
3+
// DO NOT MODIFY BY HAND.
44

55

66
#if PYTHON38
@@ -84,6 +84,7 @@ public static int magic()
8484
public static int tp_version_tag = 0;
8585
public static int tp_finalize = 0;
8686
public static int tp_vectorcall = 0;
87+
public static int tp_print = 0;
8788
public static int am_await = 0;
8889
public static int am_aiter = 0;
8990
public static int am_anext = 0;
@@ -149,4 +150,3 @@ public static int magic()
149150
}
150151

151152
#endif
152-

src/runtime/metatype.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ private static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType)
266266
return Runtime.PyFalse;
267267
}
268268

269+
Runtime.XIncref(args);
269270
using (var argsObj = new PyList(args))
270271
{
271272
if (argsObj.Length() != 1)

src/runtime/methodwrapper.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,43 @@ internal class MethodWrapper
1212
{
1313
public IntPtr mdef;
1414
public IntPtr ptr;
15+
private bool _disposed = false;
16+
17+
private ThunkInfo _thunk;
1518

1619
public MethodWrapper(Type type, string name, string funcType = null)
1720
{
1821
// Turn the managed method into a function pointer
1922

20-
IntPtr fp = Interop.GetThunk(type.GetMethod(name), funcType);
23+
_thunk = Interop.GetThunk(type.GetMethod(name), funcType);
2124

2225
// Allocate and initialize a PyMethodDef structure to represent
2326
// the managed method, then create a PyCFunction.
2427

2528
mdef = Runtime.PyMem_Malloc(4 * IntPtr.Size);
26-
TypeManager.WriteMethodDef(mdef, name, fp, 0x0003);
29+
TypeManager.WriteMethodDef(mdef, name, _thunk.Address, 0x0003);
2730
ptr = Runtime.PyCFunction_NewEx(mdef, IntPtr.Zero, IntPtr.Zero);
2831
}
2932

3033
public IntPtr Call(IntPtr args, IntPtr kw)
3134
{
3235
return Runtime.PyCFunction_Call(ptr, args, kw);
3336
}
37+
38+
public void Release()
39+
{
40+
if (_disposed)
41+
{
42+
return;
43+
}
44+
_disposed = true;
45+
bool freeDef = Runtime.Refcount(ptr) == 1;
46+
Runtime.XDecref(ptr);
47+
if (freeDef && mdef != IntPtr.Zero)
48+
{
49+
Runtime.PyMem_Free(mdef);
50+
mdef = IntPtr.Zero;
51+
}
52+
}
3453
}
3554
}

src/runtime/moduleobject.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ internal class CLRModule : ModuleObject
316316
internal static bool _SuppressDocs = false;
317317
internal static bool _SuppressOverloads = false;
318318

319+
static CLRModule()
320+
{
321+
Reset();
322+
}
323+
319324
public CLRModule() : base("clr")
320325
{
321326
_namespace = string.Empty;

src/runtime/pythonengine.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ public static PyObject ReloadModule(PyObject module)
503503
/// </remarks>
504504
public static PyObject ModuleFromString(string name, string code)
505505
{
506-
IntPtr c = Runtime.Py_CompileString(code, "none", (IntPtr)257);
506+
IntPtr c = Runtime.Py_CompileString(code, "none", (int)RunFlagType.File);
507507
Runtime.CheckExceptionOccurred();
508508
IntPtr m = Runtime.PyImport_ExecCodeModule(name, c);
509509
Runtime.CheckExceptionOccurred();
@@ -512,7 +512,7 @@ public static PyObject ModuleFromString(string name, string code)
512512

513513
public static PyObject Compile(string code, string filename = "", RunFlagType mode = RunFlagType.File)
514514
{
515-
var flag = (IntPtr)mode;
515+
var flag = (int)mode;
516516
IntPtr ptr = Runtime.Py_CompileString(code, filename, flag);
517517
Runtime.CheckExceptionOccurred();
518518
return new PyObject(ptr);
@@ -610,7 +610,7 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals,
610610
}
611611
}
612612

613-
public enum RunFlagType
613+
public enum RunFlagType : int
614614
{
615615
Single = 256,
616616
File = 257, /* Py_file_input */

0 commit comments

Comments
 (0)