forked from pythonnet/pythonnet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdelegateobject.cs
More file actions
147 lines (121 loc) · 4.82 KB
/
delegateobject.cs
File metadata and controls
147 lines (121 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Python.Runtime
{
/// <summary>
/// Managed class that provides the implementation for reflected delegate
/// types. Delegates are represented in Python by generated type objects.
/// Each of those type objects is associated an instance of this class,
/// which provides its implementation.
/// </summary>
internal class DelegateObject : ClassBase
{
MethodBinder binder;
internal DelegateObject(Type tp) : base(tp)
{
binder = new MethodBinder(tp.GetMethod("Invoke"));
}
//====================================================================
// Given a PyObject pointer to an instance of a delegate type, return
// the true managed delegate the Python object represents (or null).
//====================================================================
private static Delegate GetTrueDelegate(IntPtr op)
{
CLRObject o = GetManagedObject(op) as CLRObject;
if (o != null)
{
Delegate d = o.inst as Delegate;
return d;
}
return null;
}
internal override bool CanSubclass()
{
return false;
}
//====================================================================
// DelegateObject __new__ implementation. The result of this is a new
// PyObject whose type is DelegateObject and whose ob_data is a handle
// to an actual delegate instance. The method wrapped by the actual
// delegate instance belongs to an object generated to relay the call
// to the Python callable passed in.
//====================================================================
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
{
DelegateObject self = (DelegateObject)GetManagedObject(tp);
if (Runtime.PyTuple_Size(args) != 1)
{
string message = "class takes exactly one argument";
return Exceptions.RaiseTypeError(message);
}
IntPtr method = Runtime.PyTuple_GetItem(args, 0);
if (Runtime.PyCallable_Check(method) != 1)
{
return Exceptions.RaiseTypeError("argument must be callable");
}
Delegate d = PythonEngine.DelegateManager.GetDelegate(self.type, method);
return CLRObject.GetInstHandle(d, self.pyHandle);
}
//====================================================================
// Implements __call__ for reflected delegate types.
//====================================================================
public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw)
{
// todo: add fast type check!
IntPtr pytype = Runtime.PyObject_TYPE(ob);
DelegateObject self = (DelegateObject)GetManagedObject(pytype);
CLRObject o = GetManagedObject(ob) as CLRObject;
if (o == null)
{
return Exceptions.RaiseTypeError("invalid argument");
}
Delegate d = o.inst as Delegate;
if (d == null)
{
return Exceptions.RaiseTypeError("invalid argument");
}
return self.binder.Invoke(ob, args, kw);
}
//====================================================================
// Implements __cmp__ for reflected delegate types.
//====================================================================
#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
public static new IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) {
if (op != Runtime.Py_EQ && op != Runtime.Py_NE)
{
Runtime.Incref(Runtime.PyNotImplemented);
return Runtime.PyNotImplemented;
}
IntPtr pytrue = Runtime.PyTrue;
IntPtr pyfalse = Runtime.PyFalse;
// swap true and false for NE
if (op != Runtime.Py_EQ)
{
pytrue = Runtime.PyFalse;
pyfalse = Runtime.PyTrue;
}
Delegate d1 = GetTrueDelegate(ob);
Delegate d2 = GetTrueDelegate(other);
if (d1 == d2)
{
Runtime.Incref(pytrue);
return pytrue;
}
Runtime.Incref(pyfalse);
return pyfalse;
}
#else
public static new int tp_compare(IntPtr ob, IntPtr other)
{
Delegate d1 = GetTrueDelegate(ob);
Delegate d2 = GetTrueDelegate(other);
if (d1 == d2)
{
return 0;
}
return -1;
}
#endif
}
}