From 7f530f2a7d7ce7a492042d752a9fab27b84478bb Mon Sep 17 00:00:00 2001 From: amos402 Date: Thu, 28 Nov 2019 03:12:01 +0800 Subject: [PATCH 1/4] Add exception helper --- .editorconfig | 2 +- src/runtime/pythonexception.cs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 9e10931d0..d64f74bc1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -25,7 +25,7 @@ dotnet_sort_system_directives_first = true dotnet_separate_import_directive_groups = true [*.cs] -csharp_new_line_before_open_brace = true +csharp_new_line_before_open_brace = all csharp_new_line_before_else = true csharp_new_line_before_catch = true csharp_new_line_before_finally = true diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 295a63b3d..8a6a24799 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; namespace Python.Runtime { @@ -190,5 +191,21 @@ public static bool Matches(IntPtr ob) { return Runtime.PyErr_ExceptionMatches(ob) != 0; } + + public static void ThrowIfIsNull(IntPtr ob) + { + if (ob == IntPtr.Zero) + { + throw new PythonException(); + } + } + + public static void ThrowIfIsNotZero(int value) + { + if (value != 0) + { + throw new PythonException(); + } + } } } From 90e44bd9c3c0f04fee2f5226145887dc57a0a174 Mon Sep 17 00:00:00 2001 From: amos402 Date: Sat, 30 Nov 2019 17:01:39 +0800 Subject: [PATCH 2/4] Make the caller of `Interop.GetThunk` handle thunk's lifecycle(unfinished) --- src/runtime/interop.cs | 53 ++++++++++++++++++++++++++---------- src/runtime/methodwrapper.cs | 6 ++-- src/runtime/typemanager.cs | 13 +++++---- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 4ae4b61e0..f59521448 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using System.Reflection; using System.Text; +using System.Collections.Generic; namespace Python.Runtime { @@ -334,7 +335,7 @@ internal class TypeFlags internal class Interop { - private static ArrayList keepAlive; + private static List keepAlive; private static Hashtable pmap; static Interop() @@ -351,8 +352,7 @@ static Interop() p[item.Name] = item; } - keepAlive = new ArrayList(); - Marshal.AllocHGlobal(IntPtr.Size); + keepAlive = new List(); pmap = new Hashtable(); pmap["tp_dealloc"] = p["DestructorFunc"]; @@ -449,7 +449,7 @@ internal static Type GetPrototype(string name) return pmap[name] as Type; } - internal static IntPtr GetThunk(MethodInfo method, string funcType = null) + internal static ThunkInfo GetThunk(MethodInfo method, string funcType = null) { Type dt; if (funcType != null) @@ -457,18 +457,15 @@ internal static IntPtr GetThunk(MethodInfo method, string funcType = null) else dt = GetPrototype(method.Name); - if (dt != null) + if (dt == null) { - IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size); - Delegate d = Delegate.CreateDelegate(dt, method); - Thunk cb = new Thunk(d); - Marshal.StructureToPtr(cb, tmp, false); - IntPtr fp = Marshal.ReadIntPtr(tmp, 0); - Marshal.FreeHGlobal(tmp); - keepAlive.Add(d); - return fp; + return ThunkInfo.Empty; } - return IntPtr.Zero; + Delegate d = Delegate.CreateDelegate(dt, method); + var info = new ThunkInfo(d); + // TODO: remove keepAlive when #958 merged, let the lifecycle of ThunkInfo transfer to caller. + keepAlive.Add(info); + return info; } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -522,4 +519,32 @@ public Thunk(Delegate d) fn = d; } } + + internal class ThunkInfo + { + public readonly Delegate Target; + public readonly IntPtr Address; + + public static readonly ThunkInfo Empty = new ThunkInfo(null); + + public ThunkInfo(Delegate target) + { + if (target == null) + { + return; + } + Target = target; + Thunk cb = new Thunk(target); + IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size); + try + { + Marshal.StructureToPtr(cb, tmp, false); + Address = Marshal.ReadIntPtr(tmp, 0); + } + finally + { + Marshal.FreeHGlobal(tmp); + } + } + } } diff --git a/src/runtime/methodwrapper.cs b/src/runtime/methodwrapper.cs index 2f3ce3ef2..8c19a7768 100644 --- a/src/runtime/methodwrapper.cs +++ b/src/runtime/methodwrapper.cs @@ -13,17 +13,19 @@ internal class MethodWrapper public IntPtr mdef; public IntPtr ptr; + private ThunkInfo _thunk; + public MethodWrapper(Type type, string name, string funcType = null) { // Turn the managed method into a function pointer - IntPtr fp = Interop.GetThunk(type.GetMethod(name), funcType); + _thunk = Interop.GetThunk(type.GetMethod(name), funcType); // Allocate and initialize a PyMethodDef structure to represent // the managed method, then create a PyCFunction. mdef = Runtime.PyMem_Malloc(4 * IntPtr.Size); - TypeManager.WriteMethodDef(mdef, name, fp, 0x0003); + TypeManager.WriteMethodDef(mdef, name, _thunk.Address, 0x0003); ptr = Runtime.PyCFunction_NewEx(mdef, IntPtr.Zero, IntPtr.Zero); } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 9a98e9ebb..80fd40d7a 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -335,16 +335,18 @@ internal static IntPtr CreateMetaType(Type impl) // 4 int-ptrs in size. IntPtr mdef = Runtime.PyMem_Malloc(3 * 4 * IntPtr.Size); IntPtr mdefStart = mdef; + ThunkInfo thunkInfo = Interop.GetThunk(typeof(MetaType).GetMethod("__instancecheck__"), "BinaryFunc"); mdef = WriteMethodDef( mdef, "__instancecheck__", - Interop.GetThunk(typeof(MetaType).GetMethod("__instancecheck__"), "BinaryFunc") + thunkInfo.Address ); + thunkInfo = Interop.GetThunk(typeof(MetaType).GetMethod("__subclasscheck__"), "BinaryFunc"); mdef = WriteMethodDef( mdef, "__subclasscheck__", - Interop.GetThunk(typeof(MetaType).GetMethod("__subclasscheck__"), "BinaryFunc") + thunkInfo.Address ); // FIXME: mdef is not used @@ -705,7 +707,8 @@ internal static void InitializeSlots(IntPtr type, Type impl) continue; } - InitializeSlot(type, Interop.GetThunk(method), name); + var thunkInfo = Interop.GetThunk(method); + InitializeSlot(type, thunkInfo.Address, name); seen.Add(name); } @@ -723,8 +726,8 @@ internal static void InitializeSlots(IntPtr type, Type impl) // These have to be defined, though, so by default we fill these with // static C# functions from this class. - var ret0 = Interop.GetThunk(((Func)Return0).Method); - var ret1 = Interop.GetThunk(((Func)Return1).Method); + var ret0 = Interop.GetThunk(((Func)Return0).Method).Address; + var ret1 = Interop.GetThunk(((Func)Return1).Method).Address; if (native != null) { From 169b1c2bc6cae0e4e61602e40e6042c9b1b63bd5 Mon Sep 17 00:00:00 2001 From: amos402 Date: Wed, 18 Dec 2019 00:41:52 +0800 Subject: [PATCH 3/4] Resolve merge conflict --- src/runtime/typemanager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index ba686a703..bb920b74f 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -204,8 +204,8 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) static void InitializeSlot(IntPtr type, int slotOffset, MethodInfo method) { - IntPtr thunk = Interop.GetThunk(method); - Marshal.WriteIntPtr(type, slotOffset, thunk); + var thunk = Interop.GetThunk(method); + Marshal.WriteIntPtr(type, slotOffset, thunk.Address); } internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) From a2e43ec419228ce51c852288aa76251cc4d4c71a Mon Sep 17 00:00:00 2001 From: amos402 Date: Wed, 18 Dec 2019 00:45:21 +0800 Subject: [PATCH 4/4] Use Marshal.GetFunctionPointerForDelegate instead of Marshal + Thunk --- src/runtime/interop.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index f59521448..0f813c2d1 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -534,17 +534,7 @@ public ThunkInfo(Delegate target) return; } Target = target; - Thunk cb = new Thunk(target); - IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size); - try - { - Marshal.StructureToPtr(cb, tmp, false); - Address = Marshal.ReadIntPtr(tmp, 0); - } - finally - { - Marshal.FreeHGlobal(tmp); - } + Address = Marshal.GetFunctionPointerForDelegate(target); } } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy