10000 Simplify MethodDefs, implement __subclasscheck__. · pythonnet/pythonnet@49b01b0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 49b01b0

Browse files
committed
Simplify MethodDefs, implement __subclasscheck__.
1 parent 6fd91b2 commit 49b01b0

File tree

5 files changed

+73
-33
lines changed

5 files changed

+73
-33
lines changed

src/runtime/importhook.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ internal static void Initialize() {
4545
IntPtr mod = Runtime.PyDict_GetItemString(dict, "__builtin__");
4646
py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
4747
#endif
48-
hook = new MethodWrapper(typeof(ImportHook), "__import__");
49-
Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
48+
hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc");
49+
Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
5050
Runtime.Decref(hook.ptr);
5151

5252
root = new CLRModule();

src/runtime/interop.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ public static void FreeModuleDef(IntPtr ptr) {
249249
// } PyModuleDef
250250

251251
public static int name = 0;
252-
}
252+
}
253253
#endif // PYTHON3
254254

255255
/// <summary>
@@ -445,17 +445,19 @@ static Interop() {
445445
pmap["bf_getwritebuffer"] = p["IntObjArgFunc"];
446446
pmap["bf_getsegcount"] = p["ObjObjFunc"];
447447
pmap["bf_getcharbuffer"] = p["IntObjArgFunc"];
448-
449-
pmap["__import__"] = p["TernaryFunc"];
450-
pmap["__instancecheck__"] = p["BinaryFunc"];
451448
}
452449

453450
internal static Type GetPrototype(string name) {
454451
return pmap[name] as Type;
455452
}
456453

457-
internal static IntPtr GetThunk(MethodInfo method) {
458-
Type dt = Interop.GetPrototype(method.Name);
454+
internal static IntPtr GetThunk(MethodInfo method, string funcType = null) {
455+
Type dt;
456+
if (funcType != null)
457+
dt = typeof(Interop).GetNestedType(funcType) as Type;
458+
else
459+
dt = GetPrototype(method.Name);
460+
459461
if (dt != null) {
460462
IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size);
461463
Delegate d = Delegate.CreateDelegate(dt, method);

src/runtime/metatype.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,20 +260,24 @@ public static void tp_dealloc(IntPtr tp) {
260260
return;
261261
}
262262

263-
public static IntPtr __instancecheck__(IntPtr tp, IntPtr args)
263+
static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType)
264264
{
265265
ClassBase cb = GetManagedObject(tp) as ClassBase;
266-
266+
267267
if (cb == null)
268268
return Runtime.PyFalse;
269-
269+
270270
using (PyList argsObj = new PyList(args))
271271
{
272272
if (argsObj.Length() != 1)
273273
return Exceptions.RaiseTypeError("Invalid parameter count");
274-
274+
275275
PyObject arg = argsObj[0];
276-
PyObject otherType = arg.GetPythonType();
276+
PyObject otherType;
277+
if (checkType)
278+
otherType = arg;
279+
else
280+
otherType = arg.GetPythonType();
277281

278282
if (Runtime.PyObject_TYPE(otherType.Handle) != PyCLRMetaType)
279283
return Runtime.PyFalse;
@@ -284,6 +288,16 @@ public static IntPtr __instancecheck__(IntPtr tp, IntPtr args)
284288

285289
return Converter.ToPython(cb.type.IsAssignableFrom(otherCb.type));
286290
}
291+
}
292+
293+
public static IntPtr __instancecheck__(IntPtr tp, IntPtr args)
294+
{
295+
return DoInstanceCheck(tp, args, false);
287296
}
297+
298+
public static IntPtr __subclasscheck__(IntPtr tp, IntPtr args)
299+
{
300+
return DoInstanceCheck(tp, args, true);
301+
}
288302
}
289303
}

src/runtime/methodwrapper.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,17 @@ internal class MethodWrapper {
2525
public IntPtr mdef;
2626
public IntPtr ptr;
2727

28-
public MethodWrapper(Type type, string name) {
28+
public MethodWrapper(Type type, string name, string funcType = null) {
2929

3030
// Turn the managed method into a function pointer
3131

32-
IntPtr fp = Interop.GetThunk(type.GetMethod(name));
32+
IntPtr fp = Interop.GetThunk(type.GetMethod(name), funcType);
3333

3434
// Allocate and initialize a PyMethodDef structure to represent
3535
// the managed method, then create a PyCFunction.
3636

3737
mdef = Runtime.PyMem_Malloc(4 * IntPtr.Size);
38-
Marshal.WriteIntPtr(mdef, Marshal.StringToHGlobalAnsi(name));
39-
Marshal.WriteIntPtr(mdef, (1 * IntPtr.Size), fp);
40-
Marshal.WriteInt32(mdef, (2 * IntPtr.Size), 0x0003); // METH_VARARGS | METH_KEYWORDS
41-
Marshal.WriteIntPtr(mdef, (3 * IntPtr.Size), IntPtr.Zero);
38+
TypeManager.WriteMethodDef(mdef, name, fp, 0x0003);
4239
ptr = Runtime.PyCFunction_NewEx(mdef, IntPtr.Zero, IntPtr.Zero);
4340
}
4441

src/runtime/typemanager.cs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,28 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
267267
}
268268
}
269269

270+
internal static IntPtr WriteMethodDef(IntPtr mdef, IntPtr name, IntPtr func, int flags, IntPtr doc)
271+
{
272+
Marshal.WriteIntPtr(mdef, name);
273+
Marshal.WriteIntPtr(mdef, (1 * IntPtr.Size), func);
274+
Marshal.WriteInt32(mdef, (2 * IntPtr.Size), flags);
275+
Marshal.WriteIntPtr(mdef, (3 * IntPtr.Size), doc);
276+
return mdef + 4 * IntPtr.Size;
277+
}
278+
279+
internal static IntPtr WriteMethodDef(IntPtr mdef, string name, IntPtr func, int flags = 0x0001, string doc = null)
280+
{
281+
IntPtr namePtr = Marshal.StringToHGlobalAnsi(name);
282+
IntPtr docPtr = doc != null ? Marshal.StringToHGlobalAnsi(doc) : IntPtr.Zero;
283+
284+
return WriteMethodDef(mdef, namePtr, func, flags, docPtr);
285+
}
286+
287+
internal static IntPtr WriteMethodDefSentinel(IntPtr mdef)
288+
{
289+
return WriteMethodDef(mdef, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero);
290+
}
291+
270292
internal static IntPtr CreateMetaType(Type impl) {
271293

272294
// The managed metatype is functionally little different than the
@@ -302,20 +324,25 @@ internal static IntPtr CreateMetaType(Type impl) {
302324
flags |= TypeFlags.HaveGC;
303325
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
304326

305-
IntPtr fp = Interop.GetThunk(typeof(MetaType).GetMethod("__instancecheck__"));
306-
IntPtr mdef = Runtime.PyMem_Malloc(5 * IntPtr.Size);
307-
Marshal.WriteIntPtr(mdef, Marshal.StringToHGlobalAnsi("__instancecheck__"));
308-
Marshal.WriteIntPtr(mdef, (1 * IntPtr.Size), fp);
309-
Marshal.WriteInt32(mdef, (2 * IntPtr.Size), 0x0001);
310-
Marshal.WriteIntPtr(mdef, (3 * IntPtr.Size), IntPtr.Zero);
311-
312-
// Write empty sentinel struct
313-
Marshal.WriteIntPtr(mdef, (4 * IntPtr.Size), IntPtr.Zero);
314-
Marshal.WriteIntPtr(mdef, (5 * IntPtr.Size), IntPtr.Zero);
315-
Marshal.WriteIntPtr(mdef, (6 * IntPtr.Size), IntPtr.Zero);
316-
Marshal.WriteIntPtr(mdef, (7 * IntPtr.Size), IntPtr.Zero);
317-
318-
Marshal.WriteIntPtr(type, TypeOffset.tp_methods, mdef);
327+
// We need space for 3 PyMethodDef structs, each of them
328+
// 4 int-ptrs in size.
329+
IntPtr mdef = Runtime.PyMem_Malloc(3 * (4 * IntPtr.Size));
330+
IntPtr mdefStart = mdef;
331+
mdef = WriteMethodDef(
332+
mdef,
333+
"__instancecheck__",
334+
Interop.GetThunk(typeof(MetaType).GetMethod("__instancecheck__"), "BinaryFunc")
335+
);
336+
337+
mdef = WriteMethodDef(
338+
mdef,
339+
"__subclasscheck__",
340+
Interop.GetThunk(typeof(MetaType).GetMethod("__subclasscheck__"), "BinaryFunc")
341+
);
342+
343+
mdef = WriteMethodDefSentinel(mdef);
344+
345+
Marshal.WriteIntPtr(type, TypeOffset.tp_methods, mdefStart);
319346

320347
Runtime.PyType_Ready(type);
321348

0 commit comments

Comments
 (0)
0