Skip to content

Commit

Permalink
Add the latest ExtensionClass.h
Browse files Browse the repository at this point in the history
  • Loading branch information
stephan-hof committed Feb 22, 2017
1 parent 50b527e commit e6e74d2
Showing 1 changed file with 55 additions and 75 deletions.
130 changes: 55 additions & 75 deletions include/ExtensionClass/ExtensionClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,61 +19,61 @@
Extension Class Definitions
Implementing base extension classes
A base extension class is implemented in much the same way that an
extension type is implemented, except:
- The include file, 'ExtensionClass.h', must be included.
- The type structure is declared to be of type
'PyExtensionClass', rather than of type 'PyTypeObject'.
'PyExtensionClass', rather than of type 'PyTypeObject'.
- The type structure has an additional member that must be defined
after the documentation string. This extra member is a method chain
('PyMethodChain') containing a linked list of method definition
('PyMethodDef') lists. Method chains can be used to implement
method inheritance in C. Most extensions don't use method chains,
but simply define method lists, which are null-terminated arrays
of method definitions. A macro, 'METHOD_CHAIN' is defined in
'ExtensionClass.h' that converts a method list to a method chain.
(See the example below.)
after the documentation string. This extra member is a method chain
('PyMethodChain') containing a linked list of method definition
('PyMethodDef') lists. Method chains can be used to implement
method inheritance in C. Most extensions don't use method chains,
but simply define method lists, which are null-terminated arrays
of method definitions. A macro, 'METHOD_CHAIN' is defined in
'ExtensionClass.h' that converts a method list to a method chain.
(See the example below.)
- Module functions that create new instances must be replaced by an
'__init__' method that initializes, but does not create storage for
instances.
'__init__' method that initializes, but does not create storage for
instances.
- The extension class must be initialized and exported to the module
with::
PyExtensionClass_Export(d,"name",type);
where 'name' is the module name and 'type' is the extension class
type object.
with::
PyExtensionClass_Export(d,"name",type);
where 'name' is the module name and 'type' is the extension class
type object.
Attribute lookup
Attribute lookup is performed by calling the base extension class
'getattr' operation for the base extension class that includes C
data, or for the first base extension class, if none of the base
extension classes include C data. 'ExtensionClass.h' defines a
macro 'Py_FindAttrString' that can be used to find an object's
attributes that are stored in the object's instance dictionary or
in the object's class or base classes::
v = Py_FindAttrString(self,name);
In addition, a macro is provided that replaces 'Py_FindMethod'
calls with logic to perform the same sort of lookup that is
provided by 'Py_FindAttrString'.
Attribute lookup is performed by calling the base extension class
'getattr' operation for the base extension class that includes C
data, or for the first base extension class, if none of the base
extension classes include C data. 'ExtensionClass.h' defines a
macro 'Py_FindAttrString' that can be used to find an object's
attributes that are stored in the object's instance dictionary or
in the object's class or base classes::
v = Py_FindAttrString(self,name);
In addition, a macro is provided that replaces 'Py_FindMethod'
calls with logic to perform the same sort of lookup that is
provided by 'Py_FindAttrString'.
Linking
The extension class mechanism was designed to be useful with
dynamically linked extension modules. Modules that implement
extension classes do not have to be linked against an extension
class library. The macro 'PyExtensionClass_Export' imports the
'ExtensionClass' module and uses objects imported from this module
to initialize an extension class with necessary behavior.
The extension class mechanism was designed to be useful with
dynamically linked extension modules. Modules that implement
extension classes do not have to be linked against an extension
class library. The macro 'PyExtensionClass_Export' imports the
'ExtensionClass' module and uses objects imported from this module
to initialize an extension class with necessary behavior.
*/

Expand Down Expand Up @@ -106,7 +106,7 @@ static struct ExtensionClassCAPIstruct {


PyObject *(*EC_findiattrs_)(PyObject *self, char *cname);
int (*PyExtensionClass_Export_)(PyObject *dict, char *name,
int (*PyExtensionClass_Export_)(PyObject *dict, char *name,
PyTypeObject *typ);
PyObject *(*PyECMethod_New_)(PyObject *callable, PyObject *inst);
PyExtensionClass *ECBaseType_;
Expand All @@ -128,7 +128,7 @@ static struct ExtensionClassCAPIstruct {
lookup methods or attributes that are not managed by the base type
directly. The macro is generally used to search for attributes
after other attribute searches have failed.
Note that in Python 1.4, a getattr operation may be provided that
uses an object argument. Classes that support this new operation
should use Py_FindAttr.
Expand All @@ -145,7 +145,7 @@ static struct ExtensionClassCAPIstruct {
lookup methods or attributes that are not managed by the base type
directly. The macro is generally used to search for attributes
after other attribute searches have failed.
Note that in Python 1.4, a getattr operation may be provided that
uses an object argument. Classes that support this new operation
should use Py_FindAttr.
Expand Down Expand Up @@ -179,9 +179,9 @@ static struct ExtensionClassCAPIstruct {

/* The following macro checks whether an instance is an extension instance: */
#define PyExtensionInstance_Check(INST) \
PyObject_TypeCheck(((PyObject*)(INST))->ob_type, ECExtensionClassType)
PyObject_TypeCheck(Py_TYPE(INST), ECExtensionClassType)

#define CHECK_FOR_ERRORS(MESS)
#define CHECK_FOR_ERRORS(MESS)

/* The following macro can be used to define an extension base class
that only provides method and that is used as a pure mix-in class. */
Expand All @@ -208,27 +208,25 @@ static PyExtensionClass NAME ## Type = { PyVarObject_HEAD_INIT(NULL, 0) # NAME,
PyExtensionClassCAPI->PyECMethod_New_((CALLABLE),(INST))

/* Return the instance that is bound by an extension class method. */
#define PyECMethod_Self(M) \
(PyMethod_Check((M)) ? ((PyMethodObject*)(M))->im_self : NULL)
#define PyECMethod_Self(M) (PyMethod_Check((M)) ? PyMethod_GET_SELF(M) : NULL)

/* Check whether an object has an __of__ method for returning itself
in the context of it's container. */
#define has__of__(O) (PyObject_TypeCheck((O)->ob_type, ECExtensionClassType) \
&& (O)->ob_type->tp_descr_get != NULL)
#define has__of__(O) (PyExtensionInstance_Check(O) && Py_TYPE(O)->tp_descr_get != NULL)

/* The following macros are used to check whether an instance
or a class' instanses have instance dictionaries: */
#define HasInstDict(O) (_PyObject_GetDictPtr(O) != NULL)

#define ClassHasInstDict(C) ((C)->tp_dictoffset > 0))
#define ClassHasInstDict(C) ((C)->tp_dictoffset > 0)

/* Get an object's instance dictionary. Use with caution */
#define INSTANCE_DICT(inst) (_PyObject_GetDictPtr(O))

/* Test whether an ExtensionClass, S, is a subclass of ExtensionClass C. */
#define ExtensionClassSubclass_Check(S,C) PyType_IsSubtype((S), (C))

/* Test whether an ExtensionClass instance , I, is a subclass of
/* Test whether an ExtensionClass instance , I, is a subclass of
ExtensionClass C. */
#define ExtensionClassSubclassInstance_Check(I,C) PyObject_TypeCheck((I), (C))

Expand All @@ -246,22 +244,4 @@ static PyExtensionClass NAME ## Type = { PyVarObject_HEAD_INIT(NULL, 0) # NAME,
((PyExtensionClassCAPI != NULL) || \
(PyExtensionClassCAPI = PyCapsule_Import("ExtensionClass.CAPI2", 0)))


/* These are being overridded to use tp_free when used with
new-style classes. This is to allow old extention-class code
to work.
*/

#undef PyMem_DEL
#undef PyObject_DEL

#define PyMem_DEL(O) \
if (((O)->ob_type->tp_flags & Py_TPFLAGS_HAVE_CLASS) \
&& ((O)->ob_type->tp_free != NULL)) \
(O)->ob_type->tp_free((PyObject*)(O)); \
else \
PyObject_FREE((O));

#define PyObject_DEL(O) PyMem_DEL(O)

#endif /* EXTENSIONCLASS_H */

0 comments on commit e6e74d2

Please sign in to comment.