1 /*****************************************************************************
2 
3   Copyright (c) 1996-2002 Zope Foundation and Contributors.
4   All Rights Reserved.
5 
6   This software is subject to the provisions of the Zope Public License,
7   Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9   WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10   WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11   FOR A PARTICULAR PURPOSE
12 
13  ****************************************************************************/
14 
15 /*
16 
17   $Id$
18 
19   Extension Class Definitions
20 
21   Implementing base extension classes
22 
23     A base extension class is implemented in much the same way that an
24     extension type is implemented, except:
25 
26     - The include file, 'ExtensionClass.h', must be included.
27 
28     - The type structure is declared to be of type
29       'PyExtensionClass', rather than of type 'PyTypeObject'.
30 
31     - The type structure has an additional member that must be defined
32       after the documentation string.  This extra member is a method chain
33       ('PyMethodChain') containing a linked list of method definition
34       ('PyMethodDef') lists.  Method chains can be used to implement
35       method inheritance in C.  Most extensions don't use method chains,
36       but simply define method lists, which are null-terminated arrays
37       of method definitions.  A macro, 'METHOD_CHAIN' is defined in
38       'ExtensionClass.h' that converts a method list to a method chain.
39       (See the example below.)
40 
41     - Module functions that create new instances must be replaced by an
42       '__init__' method that initializes, but does not create storage for
43       instances.
44 
45     - The extension class must be initialized and exported to the module
46       with::
47 
48           PyExtensionClass_Export(d,"name",type);
49 
50       where 'name' is the module name and 'type' is the extension class
51       type object.
52 
53     Attribute lookup
54 
55       Attribute lookup is performed by calling the base extension class
56       'getattr' operation for the base extension class that includes C
57       data, or for the first base extension class, if none of the base
58       extension classes include C data.  'ExtensionClass.h' defines a
59       macro 'Py_FindAttrString' that can be used to find an object's
60       attributes that are stored in the object's instance dictionary or
61       in the object's class or base classes::
62 
63          v = Py_FindAttrString(self,name);
64 
65     In addition, a macro is provided that replaces 'Py_FindMethod'
66     calls with logic to perform the same sort of lookup that is
67     provided by 'Py_FindAttrString'.
68 
69     Linking
70 
71       The extension class mechanism was designed to be useful with
72       dynamically linked extension modules.  Modules that implement
73       extension classes do not have to be linked against an extension
74       class library.  The macro 'PyExtensionClass_Export' imports the
75       'ExtensionClass' module and uses objects imported from this module
76       to initialize an extension class with necessary behavior.
77 
78 */
79 
80 #ifndef EXTENSIONCLASS_H
81 #define EXTENSIONCLASS_H
82 
83 #include "Python.h"
84 #include "import.h"
85 
86 /* Declarations for objects of type ExtensionClass */
87 
88 #define EC PyTypeObject
89 #define PyExtensionClass PyTypeObject
90 
91 #define EXTENSIONCLASS_BINDABLE_FLAG      1 << 2
92 #define EXTENSIONCLASS_NOINSTDICT_FLAG    1 << 5
93 
94 typedef struct {
95   PyObject_HEAD
96 } _emptyobject;
97 
98 static struct ExtensionClassCAPIstruct {
99 
100 /*****************************************************************************
101 
102   WARNING: THIS STRUCT IS PRIVATE TO THE EXTENSION CLASS INTERFACE
103            IMPLEMENTATION AND IS SUBJECT TO CHANGE !!!
104 
105  *****************************************************************************/
106 
107 
108   PyObject *(*EC_findiattrs_)(PyObject *self, char *cname);
109   int (*PyExtensionClass_Export_)(PyObject *dict, char *name,
110                                   PyTypeObject *typ);
111   PyObject *(*PyECMethod_New_)(PyObject *callable, PyObject *inst);
112   PyExtensionClass *ECBaseType_;
113   PyExtensionClass *ECExtensionClassType_;
114 }  *PyExtensionClassCAPI = NULL;
115 
116 #define ECBaseType (PyExtensionClassCAPI->ECBaseType_)
117 #define ECExtensionClassType (PyExtensionClassCAPI->ECExtensionClassType_)
118 
119 /* Following are macros that are needed or useful for defining extension
120    classes:
121    */
122 
123 /* This macro redefines Py_FindMethod to do attribute for an attribute
124    name given by a C string lookup using extension class meta-data.
125    This is used by older getattr implementations.
126 
127    This macro is used in base class implementations of tp_getattr to
128    lookup methods or attributes that are not managed by the base type
129    directly.  The macro is generally used to search for attributes
130    after other attribute searches have failed.
131 
132    Note that in Python 1.4, a getattr operation may be provided that
133    uses an object argument. Classes that support this new operation
134    should use Py_FindAttr.
135    */
136 
137 #define EC_findiattrs (PyExtensionClassCAPI->EC_findiattrs_)
138 
139 #define Py_FindMethod(M,SELF,NAME) (EC_findiattrs((SELF),(NAME)))
140 
141 /* Do method or attribute lookup for an attribute name given by a C
142    string using extension class meta-data.
143 
144    This macro is used in base class implementations of tp_getattro to
145    lookup methods or attributes that are not managed by the base type
146    directly.  The macro is generally used to search for attributes
147    after other attribute searches have failed.
148 
149    Note that in Python 1.4, a getattr operation may be provided that
150    uses an object argument. Classes that support this new operation
151    should use Py_FindAttr.
152    */
153 #define Py_FindAttrString(SELF,NAME)  (EC_findiattrs((SELF),(NAME)))
154 
155 /* Do method or attribute lookup using extension class meta-data.
156 
157    This macro is used in base class implementations of tp_getattr to
158    lookup methods or attributes that are not managed by the base type
159    directly.  The macro is generally used to search for attributes
160    after other attribute searches have failed.  */
161 #define Py_FindAttr (ECBaseType->tp_getattro)
162 
163 /* Do attribute assignment for an attribute.
164 
165    This macro is used in base class implementations of tp_setattro to
166    set attributes that are not managed by the base type directly.  The
167    macro is generally used to assign attributes after other attribute
168    attempts to assign attributes have failed.
169    */
170 #define PyEC_SetAttr(SELF,NAME,V) (ECBaseType->tp_setattro(SELF, NAME, V))
171 
172 
173 /* Convert a method list to a method chain.  */
174 #define METHOD_CHAIN(DEF) (traverseproc)(DEF)
175 
176 /* The following macro checks whether a type is an extension class: */
177 #define PyExtensionClass_Check(TYPE) \
178   PyObject_TypeCheck((PyObject*)(TYPE), ECExtensionClassType)
179 
180 /* The following macro checks whether an instance is an extension instance: */
181 #define PyExtensionInstance_Check(INST) \
182   PyObject_TypeCheck(Py_TYPE(INST), ECExtensionClassType)
183 
184 #define CHECK_FOR_ERRORS(MESS)
185 
186 /* The following macro can be used to define an extension base class
187    that only provides method and that is used as a pure mix-in class. */
188 #define PURE_MIXIN_CLASS(NAME,DOC,METHODS) \
189 static PyExtensionClass NAME ## Type = { PyVarObject_HEAD_INIT(NULL, 0) # NAME, \
190    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
191    0 , DOC, (traverseproc)METHODS, }
192 
193 /* The following macros provide limited access to extension-class
194    method facilities. */
195 
196 /* Test for an ExtensionClass method: */
197 #define PyECMethod_Check(O) PyMethod_Check((O))
198 
199 /* Create a method object that wraps a callable object and an
200    instance. Note that if the callable object is an extension class
201    method, then the new method will wrap the callable object that is
202    wrapped by the extension class method.  Also note that if the
203    callable object is an extension class method with a reference
204    count of 1, then the callable object will be rebound to the
205    instance and returned with an incremented reference count.
206    */
207 #define PyECMethod_New(CALLABLE, INST) \
208   PyExtensionClassCAPI->PyECMethod_New_((CALLABLE),(INST))
209 
210 /* Return the instance that is bound by an extension class method. */
211 #define PyECMethod_Self(M) (PyMethod_Check((M)) ? PyMethod_GET_SELF(M) : NULL)
212 
213 /* Check whether an object has an __of__ method for returning itself
214    in the context of it's container. */
215 #define has__of__(O) (PyExtensionInstance_Check(O) && Py_TYPE(O)->tp_descr_get != NULL)
216 
217 /* The following macros are used to check whether an instance
218    or a class' instanses have instance dictionaries: */
219 #define HasInstDict(O) (_PyObject_GetDictPtr(O) != NULL)
220 
221 #define ClassHasInstDict(C) ((C)->tp_dictoffset > 0)
222 
223 /* Get an object's instance dictionary.  Use with caution */
224 #define INSTANCE_DICT(inst) (_PyObject_GetDictPtr(O))
225 
226 /* Test whether an ExtensionClass, S, is a subclass of ExtensionClass C. */
227 #define ExtensionClassSubclass_Check(S,C) PyType_IsSubtype((S), (C))
228 
229 /* Test whether an ExtensionClass instance , I, is a subclass of
230    ExtensionClass C. */
231 #define ExtensionClassSubclassInstance_Check(I,C) PyObject_TypeCheck((I), (C))
232 
233 
234 /* Export an Extension Base class in a given module dictionary with a
235    given name and ExtensionClass structure.
236    */
237 
238 #define PyExtensionClass_Export(D,N,T) \
239   if (! ExtensionClassImported || \
240       PyExtensionClassCAPI->PyExtensionClass_Export_((D),(N),&(T)) < 0) return NULL;
241 
242 
243 #define ExtensionClassImported \
244   ((PyExtensionClassCAPI != NULL) || \
245    (PyExtensionClassCAPI = PyCapsule_Import("ExtensionClass.CAPI2", 0)))
246 
247 #endif /* EXTENSIONCLASS_H */
248