From af4f0b3c6c5b7f7591b40fd514c265fd40614021 Mon Sep 17 00:00:00 2001 From: stephan-hof Date: Wed, 22 Feb 2017 07:20:31 +0100 Subject: [PATCH] Add the latest ExtensionClass.h --- include/ExtensionClass/ExtensionClass.h | 130 ++++++++++-------------- 1 file changed, 55 insertions(+), 75 deletions(-) diff --git a/include/ExtensionClass/ExtensionClass.h b/include/ExtensionClass/ExtensionClass.h index e81181a..4b7e84d 100644 --- a/include/ExtensionClass/ExtensionClass.h +++ b/include/ExtensionClass/ExtensionClass.h @@ -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. */ @@ -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_; @@ -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. @@ -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. @@ -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. */ @@ -208,19 +208,17 @@ 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)) @@ -228,7 +226,7 @@ static PyExtensionClass NAME ## Type = { PyVarObject_HEAD_INIT(NULL, 0) # NAME, /* 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)) @@ -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 */