diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 385c7f94c672f2..0600f361000525 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -147,6 +147,10 @@ Quick Reference +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ | :c:member:`~PyTypeObject.tp_vectorcall` | :c:type:`vectorcallfunc` | | | | | | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ + | :c:member:`~PyTypeObject.tp_obj_offset` | const Py_ssize_t | | | X | ~ | | + +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ + | :c:member:`~PyTypeObject.tp_obj_size` | const Py_ssize_t | | | X | ~ | | + +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ .. [#slots] A slot name in parentheses indicates it is (effectively) deprecated. @@ -1015,6 +1019,12 @@ and :c:type:`PyType_Type` effectively act as defaults.) :c:func:`PyType_HasFeature` takes a type and a flags value, *tp* and *f*, and checks whether ``tp->tp_flags & f`` is non-zero. + .. data:: Py_TPFLAGS_USES_OPAQUE_OBJECT + + This bit is set when the type object's :c:member:`PyTypeObject.tp_basicsize` is configured + for an opaque :c:type:`PyObject` structure. The value of :c:member:`PyTypeObject.tp_basicsize` is the size of the type's + internal object structure EXCLUDING the base type's structure size. + .. data:: Py_TPFLAGS_HEAPTYPE This bit is set when the type object itself is allocated on the heap, for diff --git a/Include/cpython/object.h b/Include/cpython/object.h index ae3920d4508e14..e9182e8ee4b924 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -263,6 +263,10 @@ struct _typeobject { destructor tp_finalize; vectorcallfunc tp_vectorcall; + + /* INTERNAL USE ONLY! MODIFYING THIS CAN CRASH PYTHON! */ + const Py_ssize_t tp_obj_offset; /* Offset from "PyObject *" pointer */ + const Py_ssize_t tp_obj_size; /* Total memory allocation size */ }; /* The *real* layout of a type object when allocated on the heap */ diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h index 15999a239f7a9a..645f0f35248c54 100644 --- a/Include/cpython/objimpl.h +++ b/Include/cpython/objimpl.h @@ -18,10 +18,11 @@ # error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2" #endif -#define _PyObject_VAR_SIZE(typeobj, nitems) \ - _Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \ - (nitems)*(typeobj)->tp_itemsize, \ - SIZEOF_VOID_P) +static inline Py_ssize_t _PyObject_VAR_SIZE(PyTypeObject *typeobj, Py_ssize_t nitems) +{ + Py_ssize_t size = (PyType_HasFeature(typeobj, Py_TPFLAGS_OMIT_PYOBJECT_SIZE) ? typeobj->tp_obj_size : typeobj->tp_basicsize); + return _Py_SIZE_ROUND_UP((size + (nitems * (typeobj->tp_itemsize))), SIZEOF_VOID_P); +} /* This example code implements an object constructor with a custom diff --git a/Include/object.h b/Include/object.h index 537567040f9871..16a69dc88378b7 100644 --- a/Include/object.h +++ b/Include/object.h @@ -102,26 +102,62 @@ typedef struct _typeobject PyTypeObject; * by hand. Similarly every pointer to a variable-size Python object can, * in addition, be cast to PyVarObject*. */ -typedef struct _object { + +typedef struct _object PyObject; +typedef struct _varobject PyVarObject; + +// TODO: Send "_object" and "_varobject" to CPython internal only. +struct _object { _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; PyTypeObject *ob_type; -} PyObject; +}; + +struct _varobject { + PyObject ob_base; + Py_ssize_t ob_size; /* Number of items in variable part */ +}; /* Cast argument to PyObject* type. */ #define _PyObject_CAST(op) ((PyObject*)(op)) #define _PyObject_CAST_CONST(op) ((const PyObject*)(op)) -typedef struct { - PyObject ob_base; - Py_ssize_t ob_size; /* Number of items in variable part */ -} PyVarObject; - /* Cast argument to PyVarObject* type. */ #define _PyVarObject_CAST(op) ((PyVarObject*)(op)) #define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op)) +Py_SLIB_LOCAL(Py_ssize_t) PyObject_GetRefCount(const PyObject *ob); +Py_SLIB_LOCAL(PyTypeObject *) PyObject_GetType(const PyObject *ob); + +Py_SLIB_LOCAL(void) PyObject_SetRefCount(PyObject *ob, const Py_ssize_t refcnt); +Py_SLIB_LOCAL(void) PyObject_SetType(PyObject *ob, const PyTypeObject *type); + + +Py_SLIB_LOCAL(Py_ssize_t) PyVarObject_GetSize(const PyVarObject *ob); + +Py_SLIB_LOCAL(void) PyVarObject_SetSize(PyVarObject *ob, const Py_ssize_t size); + + +Py_SLIB_LOCAL(int) PyObject_IsType(const PyObject *ob, const PyTypeObject *type); + + +Py_SLIB_LOCAL(void *) PyObject_GetStructure(const PyObject *ob, const PyTypeObject *type); +#define Py_GET_STRUCTURE(ob, type) PyObject_GetStructure(_PyObject_CAST_CONST(ob), (const PyTypeObject *)type) + +#ifdef Py_USE_SLIB +#define Py_REFCNT(ob) PyObject_GetRefCount(_PyObject_CAST_CONST(ob)) +#define Py_TYPE(ob) PyObject_GetType(_PyObject_CAST_CONST(ob)) + +#define Py_SET_REFCNT(ob, refcnt) PyObject_SetRefCount(_PyObject_CAST(ob), refcnt) +#define Py_SET_TYPE(ob, type) PyObject_SetType(_PyObject_CAST(ob), type) + +#define Py_SIZE(ob) PyVarObject_GetSize(_PyVarObject_CAST_CONST(ob)) + +#define Py_SET_SIZE(ob, size) PyVarObject_SetSize(_PyVarObject_CAST(ob), size) + +#define Py_IS_TYPE(ob, type) PyObject_IsType(_PyObject_CAST_CONST(ob), type) +#else static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) { return ob->ob_refcnt; } @@ -162,7 +198,7 @@ static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; } #define Py_SET_SIZE(ob, size) _Py_SET_SIZE(_PyVarObject_CAST(ob), size) - +#endif /* Type objects contain a string containing the type name (to help somewhat @@ -317,6 +353,9 @@ Code can use PyType_HasFeature(type_ob, flag_value) to test whether the given type object has a specified feature. */ +/* Set if the type object's tp_basicsize is set for opague object */ +#define Py_TPFLAGS_OMIT_PYOBJECT_SIZE (1UL << 8) + /* Set if the type object is dynamically allocated */ #define Py_TPFLAGS_HEAPTYPE (1UL << 9) @@ -419,6 +458,23 @@ PyAPI_FUNC(void) _Py_NegativeRefcount(const char *filename, int lineno, PyAPI_FUNC(void) _Py_Dealloc(PyObject *); +Py_SLIB_LOCAL(void) PyObject_IncRef(PyObject *op); + +Py_SLIB_LOCAL(void) PyObject_DecRef( +#ifdef Py_REF_DEBUG + const char *filename, int lineno, +#endif + PyObject *op); + +#ifdef Py_USE_SLIB +# define Py_INCREF(op) PyObject_IncRef(_PyObject_CAST(op)) + +# ifdef Py_REF_DEBUG +# define Py_DECREF(op) PyObject_DecRef(__FILE__, __LINE__, _PyObject_CAST(op)) +# else +# define Py_DECREF(op) PyObject_DecRef(_PyObject_CAST(op)) +# endif +#else static inline void _Py_INCREF(PyObject *op) { #ifdef Py_REF_DEBUG @@ -426,7 +482,6 @@ static inline void _Py_INCREF(PyObject *op) #endif op->ob_refcnt++; } - #define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op)) static inline void _Py_DECREF( @@ -449,13 +504,12 @@ static inline void _Py_DECREF( _Py_Dealloc(op); } } - #ifdef Py_REF_DEBUG # define Py_DECREF(op) _Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op)) #else # define Py_DECREF(op) _Py_DECREF(_PyObject_CAST(op)) #endif - +#endif /* Safely decref `op` and set `op` to NULL, especially useful in tp_clear * and tp_dealloc implementations. diff --git a/Include/pyport.h b/Include/pyport.h index 7137006870bf01..e93cdc2cf79e34 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -187,9 +187,11 @@ typedef int Py_ssize_clean_t; /* ignore warnings if the compiler decides not to inline a function */ # pragma warning(disable: 4710) /* fastest possible local call under MSVC */ +# define Py_SLIB_LOCAL(type) type __fastcall # define Py_LOCAL(type) static type __fastcall # define Py_LOCAL_INLINE(type) static __inline type __fastcall #else +# define Py_SLIB_LOCAL(type) type # define Py_LOCAL(type) static type # define Py_LOCAL_INLINE(type) static inline type #endif diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index aaba6630ff4396..9020e0d33b2968 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1334,7 +1334,7 @@ def delx(self): del self.__x check((1,2,3), vsize('') + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2nPI13Pl4Pn9Pn11PIPP' + fmt = 'P2nPI13Pl4Pn9Pn11PIPPll' s = vsize(fmt) check(int, s) # class diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f0e349ecd2bb92..ec521e6d993b2f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2086,11 +2086,19 @@ best_base(PyObject *bases) return base; } +static inline const Py_ssize_t get_type_totalsize(PyTypeObject *type) +{ + if (type->tp_obj_size < sizeof(PyObject)) // PyType_Type->tp_new manages to trigger this. + return type->tp_basicsize; + + return type->tp_obj_size; +} + static int extra_ivars(PyTypeObject *type, PyTypeObject *base) { - size_t t_size = type->tp_basicsize; - size_t b_size = base->tp_basicsize; + size_t t_size = get_type_totalsize(type); + size_t b_size = get_type_totalsize(base); assert(t_size >= b_size); /* Else type smaller than base! */ if (type->tp_itemsize || base->tp_itemsize) { @@ -4846,7 +4854,7 @@ object___sizeof___impl(PyObject *self) isize = Py_TYPE(self)->tp_itemsize; if (isize > 0) res = Py_SIZE(self) * isize; - res += Py_TYPE(self)->tp_basicsize; + res += get_type_totalsize(Py_TYPE(self)); return PyLong_FromSsize_t(res); } @@ -4945,7 +4953,8 @@ PyTypeObject PyBaseObject_Type = { PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | /* tp_flags */ + Py_TPFLAGS_OMIT_PYOBJECT_SIZE, object_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -5364,6 +5373,30 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) static int add_operators(PyTypeObject *); +void set_type_memory_data(PyTypeObject *type, PyTypeObject *base) +{ + // Obtain the true size of the base type. + Py_ssize_t base_size = 0, base_offset = 0; + if (base != NULL) { // Only possible if we're not dealing with PyBaseObject_Type + if (_PyType_HasFeature(base, Py_TPFLAGS_OMIT_PYOBJECT_SIZE)) { + base_size = base->tp_obj_size; + base_offset = base->tp_obj_offset; + } else { + base_size = base->tp_basicsize; + base_offset = 0; // PyObject ALWAYS occupies the start of the memory block. + } + } + + Py_ssize_t *size_ptr = (Py_ssize_t *)&type->tp_obj_size, *offset_ptr = (Py_ssize_t *)&type->tp_obj_offset; + if (_PyType_HasFeature(type, Py_TPFLAGS_OMIT_PYOBJECT_SIZE)) { + *size_ptr = base_size + type->tp_basicsize; + *offset_ptr = base_offset + base_size; // The type's internal structure occupies the next block of memory. + } else { + *size_ptr = type->tp_basicsize; // tp_basicsize already includes base_size. + *offset_ptr = 0; // The type's internal structure already includes "PyObject". + } +} + int PyType_Ready(PyTypeObject *type) { @@ -5426,6 +5459,8 @@ PyType_Ready(PyTypeObject *type) goto error; } + set_type_memory_data(type, base); + /* Initialize ob_type if NULL. This means extensions that want to be compilable separately on Windows can call PyType_Ready() instead of initializing the ob_type field of their type objects. */ diff --git a/PC/pyconfig.h b/PC/pyconfig.h index b29f63c35bccb1..2353ead1e7f74a 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -260,6 +260,10 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* All windows compilers that use this header support __declspec */ #define HAVE_DECLSPEC_DLL +#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) +# define Py_USE_SLIB +#endif + /* For an MSVC DLL, we can nominate the .lib files used by extensions */ #ifdef MS_COREDLL # if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) @@ -269,10 +273,13 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ file in their Makefile (other compilers are generally taken care of by distutils.) */ # if defined(_DEBUG) +# pragma comment(lib, "slib_python310_d.lib") # pragma comment(lib,"python310_d.lib") # elif defined(Py_LIMITED_API) +# pragma comment(lib, "slib_python310.lib") # pragma comment(lib,"python3.lib") # else +# pragma comment(lib, "slib_python310.lib") # pragma comment(lib,"python310.lib") # endif /* _DEBUG */ # endif /* _MSC_VER */ diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index 4b6dc1e6771dc3..2cf9e3638b0eb0 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -107,6 +107,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw_uwp", "pythonw_uwp. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_uuid", "_uuid.vcxproj", "{CB435430-EBB1-478B-8F4E-C256F6838F55}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slib_pythoncore", "slib_pythoncore.vcxproj", "{983BBA6B-A34B-40F8-927C-A57C714F1887}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -1508,6 +1510,34 @@ Global {CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|Win32.Build.0 = Release|Win32 {CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|x64.ActiveCfg = Release|x64 {CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|x64.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Debug|ARM.ActiveCfg = Debug|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Debug|ARM64.ActiveCfg = Debug|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Debug|Win32.ActiveCfg = Debug|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Debug|Win32.Build.0 = Debug|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Debug|x64.ActiveCfg = Debug|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Debug|x64.Build.0 = Debug|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|ARM.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|ARM.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|ARM64.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|ARM64.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|Win32.ActiveCfg = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|Win32.Build.0 = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|x64.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGInstrument|x64.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|ARM.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|ARM.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|ARM64.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|ARM64.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|Win32.ActiveCfg = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|Win32.Build.0 = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|x64.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.PGUpdate|x64.Build.0 = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Release|ARM.ActiveCfg = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Release|ARM64.ActiveCfg = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Release|Win32.ActiveCfg = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Release|Win32.Build.0 = Release|Win32 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Release|x64.ActiveCfg = Release|x64 + {983BBA6B-A34B-40F8-927C-A57C714F1887}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index ec22e6fc76e584..f7a740f0b9aedf 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -104,6 +104,11 @@ + + + {983bba6b-a34b-40f8-927c-a57c714f1887} + + diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index db26e38911bc05..5665f5815e1052 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -501,6 +501,11 @@ + + + {983bba6b-a34b-40f8-927c-a57c714f1887} + + @@ -533,7 +538,6 @@ - @@ -542,4 +546,4 @@ - + \ No newline at end of file diff --git a/PCbuild/slib_pythoncore.vcxproj b/PCbuild/slib_pythoncore.vcxproj new file mode 100644 index 00000000000000..95bab6533dd415 --- /dev/null +++ b/PCbuild/slib_pythoncore.vcxproj @@ -0,0 +1,113 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + ARM + + + PGInstrument + ARM64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + ARM + + + PGUpdate + ARM64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {983bba6b-a34b-40f8-927c-a57c714f1887} + slib_pythoncore + + + + + StaticLibrary + false + + + + + + false + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + slib_$(PyDllName) + + + Link + + + + /Zm200 %(AdditionalOptions) + $(PySourcePath)Python;%(AdditionalIncludeDirectories) + $(zlibDir);%(AdditionalIncludeDirectories) + _USRDLL;Py_BUILD_SLIB;MS_DLL_ID="$(SysWinVer)";%(PreprocessorDefinitions) + + + + + AssemblyAndSourceCode + + + + + + \ No newline at end of file diff --git a/PCbuild/slib_pythoncore.vcxproj.filters b/PCbuild/slib_pythoncore.vcxproj.filters new file mode 100644 index 00000000000000..46f286dafd724a --- /dev/null +++ b/PCbuild/slib_pythoncore.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {87f89d00-deec-4816-998c-fc76b8c42c23} + + + + + Source Files\Objects + + + \ No newline at end of file diff --git a/SLib/object.c b/SLib/object.c new file mode 100644 index 00000000000000..01117def36c4aa --- /dev/null +++ b/SLib/object.c @@ -0,0 +1,71 @@ +#include // TODO: Replace with appropriate INTERNAL ONLY header. + +Py_SLIB_LOCAL(Py_ssize_t) PyObject_GetRefCount(const PyObject *ob) { + return ob->ob_refcnt; +} + +Py_SLIB_LOCAL(PyTypeObject *) PyObject_GetType(const PyObject *ob) { + return ob->ob_type; +} + +Py_SLIB_LOCAL(void) PyObject_SetRefCount(PyObject *ob, const Py_ssize_t refcnt) { + ob->ob_refcnt = (Py_ssize_t)refcnt; +} + +Py_SLIB_LOCAL(void) PyObject_SetType(PyObject *ob, const PyTypeObject *type) { + ob->ob_type = (PyTypeObject *)type; +} + + +Py_SLIB_LOCAL(Py_ssize_t) PyVarObject_GetSize(const PyVarObject *ob) { + return ob->ob_size; +} + +Py_SLIB_LOCAL(void) PyVarObject_SetSize(PyVarObject *ob, const Py_ssize_t size) { + ob->ob_size = (Py_ssize_t)size; +} + + +Py_SLIB_LOCAL(int) PyObject_IsType(const PyObject *ob, const PyTypeObject *type) { + return Py_TYPE(ob) == type; +} + + +Py_SLIB_LOCAL(void *) PyObject_GetStructure(const PyObject *ob, const PyTypeObject *type) +{ + if (!PyType_HasFeature((PyTypeObject *)type, Py_TPFLAGS_OMIT_PYOBJECT_SIZE) || + type->tp_obj_offset == type->tp_obj_size) // This checks to see if tp_basicsize was 0 (IE: It has no internal structure) + return (void *)ob; + + return (void *)(((unsigned char *)ob) + type->tp_obj_offset); +} + + +Py_SLIB_LOCAL(void) PyObject_IncRef(PyObject *ob) +{ +#ifdef Py_REF_DEBUG + ++_Py_RefTotal; +#endif + ++ob->ob_refcnt; +} + +Py_SLIB_LOCAL(void) PyObject_DecRef( +#ifdef Py_REF_DEBUG + const char *filename, int lineno, +#endif + PyObject *ob) +{ +#ifdef Py_REF_DEBUG + --_Py_RefTotal; +#endif + if (--ob->ob_refcnt != 0) { +#ifdef Py_REF_DEBUG + if (ob->ob_refcnt < 0) { + _Py_NegativeRefcount(filename, lineno, ob); + } +#endif + } + else { + _Py_Dealloc(ob); + } +}