-
Notifications
You must be signed in to change notification settings - Fork 774
Expand file tree
/
Copy pathextensiontype.cs
More file actions
executable file
·135 lines (99 loc) · 4.29 KB
/
extensiontype.cs
File metadata and controls
executable file
·135 lines (99 loc) · 4.29 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
// ==========================================================================
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
// ==========================================================================
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
/// <summary>
/// Base class for extensions whose instances *share* a single Python
/// type object, such as the types that represent CLR methods, fields,
/// etc. Instances implemented by this class do not support subtyping.
/// </summary>
internal abstract class ExtensionType : ManagedType {
public ExtensionType() : base() {
// Create a new PyObject whose type is a generated type that is
// implemented by the particuar concrete ExtensionType subclass.
// The Python instance object is related to an instance of a
// particular concrete subclass with a hidden CLR gchandle.
IntPtr tp = TypeManager.GetTypeHandle(this.GetType());
// int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt);
// if (rc > 1050) {
// DebugUtil.Print("tp is: ", tp);
// DebugUtil.DumpType(tp);
// }
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
GCHandle gc = GCHandle.Alloc(this);
Marshal.WriteIntPtr(py, ObjectOffset.magic(), (IntPtr)gc);
// We have to support gc because the type machinery makes it very
// hard not to - but we really don't have a need for it in most
// concrete extension types, so untrack the object to save calls
// from Python into the managed runtime that are pure overhead.
Runtime.PyObject_GC_UnTrack(py);
this.tpHandle = tp;
this.pyHandle = py;
this.gcHandle = gc;
}
//====================================================================
// Common finalization code to support custom tp_deallocs.
//====================================================================
public static void FinalizeObject(ManagedType self) {
Runtime.PyObject_GC_Del(self.pyHandle);
Runtime.Decref(self.tpHandle);
self.gcHandle.Free();
}
//====================================================================
// Type __setattr__ implementation.
//====================================================================
[CallConvCdecl()]
public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) {
string message = "type does not support setting attributes";
if (val == IntPtr.Zero) {
message = "readonly attribute";
}
Exceptions.SetError(Exceptions.TypeError, message);
return -1;
}
//====================================================================
// Default __set__ implementation - this prevents descriptor instances
// being silently replaced in a type __dict__ by default __setattr__.
//====================================================================
[CallConvCdecl()]
public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) {
string message = "attribute is read-only";
Exceptions.SetError(Exceptions.AttributeError, message);
return -1;
}
//====================================================================
// Required Python GC support.
//====================================================================
[CallConvCdecl()]
public static int tp_traverse(IntPtr ob, IntPtr func, IntPtr args) {
return 0;
}
[CallConvCdecl()]
public static int tp_clear(IntPtr ob) {
return 0;
}
[CallConvCdecl()]
public static int tp_is_gc(IntPtr type) {
return 1;
}
//====================================================================
// Default dealloc implementation.
//====================================================================
[CallConvCdecl()]
public static void tp_dealloc(IntPtr ob) {
// Clean up a Python instance of this extension type. This
// frees the allocated Python object and decrefs the type.
ManagedType self = GetManagedObject(ob);
FinalizeObject(self);
}
}
}