[Python-checkins] bpo-35134: Create Include/cpython/ subdirectory (GH-10624)

Victor Stinner webhook-mailer at python.org
Fri Nov 23 11:00:05 EST 2018


https://github.com/python/cpython/commit/e421106b9e4d780c083113e4180d58d68acc69ab
commit: e421106b9e4d780c083113e4180d58d68acc69ab
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018-11-23T17:00:00+01:00
summary:

bpo-35134: Create Include/cpython/ subdirectory (GH-10624)

Include/*.h should be the "portable Python API", whereas
Include/cpython/*.h should be the "CPython API": CPython
implementation details.

Changes:

* Create Include/cpython/ subdirectory
* "make install" now creates $prefix/include/cpython and copy
  Include/cpython/* to $prefix/include/cpython
* Create Include/cpython/objimpl.h: move objimpl.h code
  surrounded by "#ifndef Py_LIMITED_API" to cpython/objimpl.h.
* objimpl.h now includes cpython/objimpl.h
* Windows installer (MSI) now also install Include/ subdirectories:
  Include/cpython/ and Include/internal/.

files:
A Include/cpython/objimpl.h
A Misc/NEWS.d/next/C API/2018-11-01-13-58-37.bpo-35134.SbZo0o.rst
M Include/objimpl.h
M Makefile.pre.in
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters
M Tools/msi/dev/dev.wixproj

diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h
new file mode 100644
index 000000000000..f121922bc42c
--- /dev/null
+++ b/Include/cpython/objimpl.h
@@ -0,0 +1,113 @@
+#ifndef Py_CPYTHON_OBJIMPL_H
+#  error "this header file must not be included directly"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This function returns the number of allocated memory blocks, regardless of size */
+PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void);
+
+/* Macros */
+#ifdef WITH_PYMALLOC
+PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out);
+#endif
+
+
+typedef struct {
+    /* user context passed as the first argument to the 2 functions */
+    void *ctx;
+
+    /* allocate an arena of size bytes */
+    void* (*alloc) (void *ctx, size_t size);
+
+    /* free an arena */
+    void (*free) (void *ctx, void *ptr, size_t size);
+} PyObjectArenaAllocator;
+
+/* Get the arena allocator. */
+PyAPI_FUNC(void) PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator);
+
+/* Set the arena allocator. */
+PyAPI_FUNC(void) PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator);
+
+
+PyAPI_FUNC(Py_ssize_t) _PyGC_CollectNoFail(void);
+PyAPI_FUNC(Py_ssize_t) _PyGC_CollectIfEnabled(void);
+
+
+/* Test if an object has a GC head */
+#define PyObject_IS_GC(o) \
+    (PyType_IS_GC(Py_TYPE(o)) \
+     && (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o)))
+
+/* GC information is stored BEFORE the object structure. */
+typedef struct {
+    // Pointer to next object in the list.
+    // 0 means the object is not tracked
+    uintptr_t _gc_next;
+
+    // Pointer to previous object in the list.
+    // Lowest two bits are used for flags documented later.
+    uintptr_t _gc_prev;
+} PyGC_Head;
+
+#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
+
+/* True if the object is currently tracked by the GC. */
+#define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0)
+
+/* True if the object may be tracked by the GC in the future, or already is.
+   This can be useful to implement some optimizations. */
+#define _PyObject_GC_MAY_BE_TRACKED(obj) \
+    (PyObject_IS_GC(obj) && \
+        (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
+
+
+/* Bit flags for _gc_prev */
+/* Bit 0 is set when tp_finalize is called */
+#define _PyGC_PREV_MASK_FINALIZED  (1)
+/* Bit 1 is set when the object is in generation which is GCed currently. */
+#define _PyGC_PREV_MASK_COLLECTING (2)
+/* The (N-2) most significant bits contain the real address. */
+#define _PyGC_PREV_SHIFT           (2)
+#define _PyGC_PREV_MASK            (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
+
+// Lowest bit of _gc_next is used for flags only in GC.
+// But it is always 0 for normal code.
+#define _PyGCHead_NEXT(g)        ((PyGC_Head*)(g)->_gc_next)
+#define _PyGCHead_SET_NEXT(g, p) ((g)->_gc_next = (uintptr_t)(p))
+
+// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
+#define _PyGCHead_PREV(g) ((PyGC_Head*)((g)->_gc_prev & _PyGC_PREV_MASK))
+#define _PyGCHead_SET_PREV(g, p) do { \
+    assert(((uintptr_t)p & ~_PyGC_PREV_MASK) == 0); \
+    (g)->_gc_prev = ((g)->_gc_prev & ~_PyGC_PREV_MASK) \
+        | ((uintptr_t)(p)); \
+    } while (0)
+
+#define _PyGCHead_FINALIZED(g) \
+    (((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0)
+#define _PyGCHead_SET_FINALIZED(g) \
+    ((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)
+
+#define _PyGC_FINALIZED(o) \
+    _PyGCHead_FINALIZED(_Py_AS_GC(o))
+#define _PyGC_SET_FINALIZED(o) \
+    _PyGCHead_SET_FINALIZED(_Py_AS_GC(o))
+
+
+PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t size);
+PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t size);
+
+
+/* Test if a type supports weak references */
+#define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0)
+
+#define PyObject_GET_WEAKREFS_LISTPTR(o) \
+    ((PyObject **) (((char *) (o)) + Py_TYPE(o)->tp_weaklistoffset))
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Include/objimpl.h b/Include/objimpl.h
index aee3fdc3747a..f475ed001d02 100644
--- a/Include/objimpl.h
+++ b/Include/objimpl.h
@@ -101,17 +101,6 @@ PyAPI_FUNC(void *) PyObject_Calloc(size_t nelem, size_t elsize);
 PyAPI_FUNC(void *) PyObject_Realloc(void *ptr, size_t new_size);
 PyAPI_FUNC(void) PyObject_Free(void *ptr);
 
-#ifndef Py_LIMITED_API
-/* This function returns the number of allocated memory blocks, regardless of size */
-PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void);
-#endif /* !Py_LIMITED_API */
-
-/* Macros */
-#ifdef WITH_PYMALLOC
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out);
-#endif /* #ifndef Py_LIMITED_API */
-#endif
 
 /* Macros */
 #define PyObject_MALLOC         PyObject_Malloc
@@ -226,24 +215,6 @@ _PyObject_INIT_VAR(PyVarObject *op, PyTypeObject *typeobj, Py_ssize_t size)
    constructor you would start directly with PyObject_Init/InitVar
 */
 
-#ifndef Py_LIMITED_API
-typedef struct {
-    /* user context passed as the first argument to the 2 functions */
-    void *ctx;
-
-    /* allocate an arena of size bytes */
-    void* (*alloc) (void *ctx, size_t size);
-
-    /* free an arena */
-    void (*free) (void *ctx, void *ptr, size_t size);
-} PyObjectArenaAllocator;
-
-/* Get the arena allocator. */
-PyAPI_FUNC(void) PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator);
-
-/* Set the arena allocator. */
-PyAPI_FUNC(void) PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator);
-#endif
 
 
 /*
@@ -254,11 +225,6 @@ PyAPI_FUNC(void) PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator);
 /* C equivalent of gc.collect() which ignores the state of gc.enabled. */
 PyAPI_FUNC(Py_ssize_t) PyGC_Collect(void);
 
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(Py_ssize_t) _PyGC_CollectNoFail(void);
-PyAPI_FUNC(Py_ssize_t) _PyGC_CollectIfEnabled(void);
-#endif
-
 /* Test if a type has a GC head */
 #define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
 
@@ -267,72 +233,7 @@ PyAPI_FUNC(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, Py_ssize_t);
                 ( (type *) _PyObject_GC_Resize(_PyVarObject_CAST(op), (n)) )
 
 
-#ifndef Py_LIMITED_API
-/* Test if an object has a GC head */
-#define PyObject_IS_GC(o) \
-    (PyType_IS_GC(Py_TYPE(o)) \
-     && (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o)))
-
-/* GC information is stored BEFORE the object structure. */
-typedef struct {
-    // Pointer to next object in the list.
-    // 0 means the object is not tracked
-    uintptr_t _gc_next;
-
-    // Pointer to previous object in the list.
-    // Lowest two bits are used for flags documented later.
-    uintptr_t _gc_prev;
-} PyGC_Head;
-
-#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
-
-/* True if the object is currently tracked by the GC. */
-#define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0)
-
-/* True if the object may be tracked by the GC in the future, or already is.
-   This can be useful to implement some optimizations. */
-#define _PyObject_GC_MAY_BE_TRACKED(obj) \
-    (PyObject_IS_GC(obj) && \
-        (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
-
-
-/* Bit flags for _gc_prev */
-/* Bit 0 is set when tp_finalize is called */
-#define _PyGC_PREV_MASK_FINALIZED  (1)
-/* Bit 1 is set when the object is in generation which is GCed currently. */
-#define _PyGC_PREV_MASK_COLLECTING (2)
-/* The (N-2) most significant bits contain the real address. */
-#define _PyGC_PREV_SHIFT           (2)
-#define _PyGC_PREV_MASK            (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
-
-// Lowest bit of _gc_next is used for flags only in GC.
-// But it is always 0 for normal code.
-#define _PyGCHead_NEXT(g)        ((PyGC_Head*)(g)->_gc_next)
-#define _PyGCHead_SET_NEXT(g, p) ((g)->_gc_next = (uintptr_t)(p))
-
-// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
-#define _PyGCHead_PREV(g) ((PyGC_Head*)((g)->_gc_prev & _PyGC_PREV_MASK))
-#define _PyGCHead_SET_PREV(g, p) do { \
-    assert(((uintptr_t)p & ~_PyGC_PREV_MASK) == 0); \
-    (g)->_gc_prev = ((g)->_gc_prev & ~_PyGC_PREV_MASK) \
-        | ((uintptr_t)(p)); \
-    } while (0)
-
-#define _PyGCHead_FINALIZED(g) \
-    (((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0)
-#define _PyGCHead_SET_FINALIZED(g) \
-    ((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)
-
-#define _PyGC_FINALIZED(o) \
-    _PyGCHead_FINALIZED(_Py_AS_GC(o))
-#define _PyGC_SET_FINALIZED(o) \
-    _PyGCHead_SET_FINALIZED(_Py_AS_GC(o))
-#endif   /* !defined(Py_LIMITED_API) */
 
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t size);
-PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t size);
-#endif /* !Py_LIMITED_API */
 PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *);
 PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t);
 
@@ -368,13 +269,10 @@ PyAPI_FUNC(void) PyObject_GC_Del(void *);
         }                                                               \
     } while (0)
 
-
-/* Test if a type supports weak references */
 #ifndef Py_LIMITED_API
-#define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0)
-
-#define PyObject_GET_WEAKREFS_LISTPTR(o) \
-    ((PyObject **) (((char *) (o)) + Py_TYPE(o)->tp_weaklistoffset))
+#  define Py_CPYTHON_OBJIMPL_H
+#  include  "cpython/objimpl.h"
+#  undef Py_CPYTHON_OBJIMPL_H
 #endif
 
 #ifdef __cplusplus
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 5a21adb7e9b1..d0e915a00ae0 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1021,9 +1021,13 @@ PYTHON_HEADERS= \
 		$(srcdir)/Include/unicodeobject.h \
 		$(srcdir)/Include/warnings.h \
 		$(srcdir)/Include/weakrefobject.h \
+		\
 		pyconfig.h \
 		$(PARSER_HEADERS) \
 		$(srcdir)/Include/Python-ast.h \
+		\
+		$(srcdir)/Include/cpython/objimpl.h \
+		\
 		$(srcdir)/Include/internal/pycore_accu.h \
 		$(srcdir)/Include/internal/pycore_atomic.h \
 		$(srcdir)/Include/internal/pycore_ceval.h \
@@ -1446,6 +1450,11 @@ inclinstall:
 		else	true; \
 		fi; \
 	done
+	@if test ! -d $(DESTDIR)$(INCLUDEPY)/cpython; then \
+		echo "Creating directory $(DESTDIR)$(INCLUDEPY)/cpython"; \
+		$(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(INCLUDEPY)/cpython; \
+	else	true; \
+	fi
 	@if test ! -d $(DESTDIR)$(INCLUDEPY)/internal; then \
 		echo "Creating directory $(DESTDIR)$(INCLUDEPY)/internal"; \
 		$(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(INCLUDEPY)/internal; \
@@ -1456,6 +1465,11 @@ inclinstall:
 		echo $(INSTALL_DATA) $$i $(INCLUDEPY); \
 		$(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY); \
 	done
+	@for i in $(srcdir)/Include/cpython/*.h; \
+	do \
+		echo $(INSTALL_DATA) $$i $(INCLUDEPY)/cpython; \
+		$(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY)/cpython; \
+	done
 	@for i in $(srcdir)/Include/internal/*.h; \
 	do \
 		echo $(INSTALL_DATA) $$i $(INCLUDEPY)/internal; \
diff --git a/Misc/NEWS.d/next/C API/2018-11-01-13-58-37.bpo-35134.SbZo0o.rst b/Misc/NEWS.d/next/C API/2018-11-01-13-58-37.bpo-35134.SbZo0o.rst
new file mode 100644
index 000000000000..c486a2951f9a
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2018-11-01-13-58-37.bpo-35134.SbZo0o.rst	
@@ -0,0 +1 @@
+Creation of a new ``Include/cpython/`` subdirectory.
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 885d602b3f0e..34cd3796888c 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -95,6 +95,7 @@
     <ClInclude Include="..\Include\complexobject.h" />
     <ClInclude Include="..\Include\context.h" />
     <ClInclude Include="..\Include\coreconfig.h" />
+    <ClInclude Include="..\Include\cpython\objimpl.h" />
     <ClInclude Include="..\Include\datetime.h" />
     <ClInclude Include="..\Include\descrobject.h" />
     <ClInclude Include="..\Include\dictobject.h" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 2af11c943ae2..ebe5e8a169fd 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -84,6 +84,9 @@
     <ClInclude Include="..\Include\coreconfig.h">
       <Filter>Include</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\cpython\objimpl.h">
+      <Filter>Include</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\datetime.h">
       <Filter>Include</Filter>
     </ClInclude>
diff --git a/Tools/msi/dev/dev.wixproj b/Tools/msi/dev/dev.wixproj
index 682b66031f1e..bc3a19ce33ca 100644
--- a/Tools/msi/dev/dev.wixproj
+++ b/Tools/msi/dev/dev.wixproj
@@ -21,7 +21,7 @@
         <EmbeddedResource Include="*.wxl" />
     </ItemGroup>
     <ItemGroup>
-        <InstallFiles Include="$(PySourcePath)include\*.h">
+        <InstallFiles Include="$(PySourcePath)include\**\*.h">
             <SourceBase>$(PySourcePath)</SourceBase>
             <Source>!(bindpath.src)</Source>
             <TargetBase>$(PySourcePath)</TargetBase>
@@ -29,7 +29,7 @@
             <Group>dev_include</Group>
         </InstallFiles>
     </ItemGroup>
-    
+
     <Target Name="BuildMinGWLib"
             Inputs="$(BuildPath)$(PyDllName).dll"
             Outputs="$(BuildPath)lib$(PyDllName).a"
@@ -46,4 +46,4 @@
     </Target>
 
     <Import Project="..\msi.targets" />
-</Project>
\ No newline at end of file
+</Project>



More information about the Python-checkins mailing list