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

Skip to content

Commit f0e9c38

Browse files
amos402filmor
authored andcommitted
Transfer the ownership of method's thunk to caller(split from #958) (#1003)
* Add exception helper * Make the caller of `Interop.GetThunk` handle thunk's lifecycle(unfinished) * Use Marshal.GetFunctionPointerForDelegate instead of Marshal + Thunk
1 parent c1190f4 commit f0e9c38

File tree

3 files changed

+43
-23
lines changed

3 files changed

+43
-23
lines changed

src/runtime/interop.cs

Lines changed: 29 additions & 14 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
{
@@ -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/methodwrapper.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ internal class MethodWrapper
1414
public IntPtr ptr;
1515
private bool _disposed = false;
1616

17+
private ThunkInfo _thunk;
18+
1719
public MethodWrapper(Type type, string name, string funcType = null)
1820
{
1921
// Turn the managed method into a function pointer
2022

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

2325
// Allocate and initialize a PyMethodDef structure to represent
2426
// the managed method, then create a PyCFunction.
2527

2628
mdef = Runtime.PyMem_Malloc(4 * IntPtr.Size);
27-
TypeManager.WriteMethodDef(mdef, name, fp, 0x0003);
29+
TypeManager.WriteMethodDef(mdef, name, _thunk.Address, 0x0003);
2830
ptr = Runtime.PyCFunction_NewEx(mdef, IntPtr.Zero, IntPtr.Zero);
2931
}
3032

src/runtime/typemanager.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
204204

205205
static void InitializeSlot(IntPtr type, int slotOffset, MethodInfo method)
206206
{
207-
IntPtr thunk = Interop.GetThunk(method);
208-
Marshal.WriteIntPtr(type, slotOffset, thunk);
207+
var thunk = Interop.GetThunk(method);
208+
Marshal.WriteIntPtr(type, slotOffset, thunk.Address);
209209
}
210210

211211
internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
@@ -344,16 +344,18 @@ internal static IntPtr CreateMetaType(Type impl)
344344
// 4 int-ptrs in size.
345345
IntPtr mdef = Runtime.PyMem_Malloc(3 * 4 * IntPtr.Size);
346346
IntPtr mdefStart = mdef;
347+
ThunkInfo thunkInfo = Interop.GetThunk(typeof(MetaType).GetMethod("__instancecheck__"), "BinaryFunc");
347348
mdef = WriteMethodDef(
348349
mdef,
349350
"__instancecheck__",
350-
Interop.GetThunk(typeof(MetaType).GetMethod("__instancecheck__"), "BinaryFunc")
351+
thunkInfo.Address
351352
);
352353

354+
thunkInfo = Interop.GetThunk(typeof(MetaType).GetMethod("__subclasscheck__"), "BinaryFunc");
353355
mdef = WriteMethodDef(
354356
mdef,
355357
"__subclasscheck__",
356-
Interop.GetThunk(typeof(MetaType).GetMethod("__subclasscheck__"), "BinaryFunc")
358+
thunkInfo.Address
357359
);
358360

359361
// FIXME: mdef is not used
@@ -710,7 +712,8 @@ internal static void InitializeSlots(IntPtr type, Type impl)
710712
continue;
711713
}
712714

713-
InitializeSlot(type, Interop.GetThunk(method), name);
715+
var thunkInfo = Interop.GetThunk(method);
716+
InitializeSlot(type, thunkInfo.Address, name);
714717

715718
seen.Add(name);
716719
}
@@ -728,8 +731,8 @@ internal static void InitializeSlots(IntPtr type, Type impl)
728731
// These have to be defined, though, so by default we fill these with
729732
// static C# functions from this class.
730733

731-
var ret0 = Interop.GetThunk(((Func<IntPtr, int>)Return0).Method);
732-
var ret1 = Interop.GetThunk(((Func<IntPtr, int>)Return1).Method);
734+
var ret0 = Interop.GetThunk(((Func<IntPtr, int>)Return0).Method).Address;
735+
var ret1 = Interop.GetThunk(((Func<IntPtr, int>)Return1).Method).Address;
733736

734737
if (native != null)
735738
{

0 commit comments

Comments
 (0)