- Issue #10181: New memoryview implementation fixes multiple ownership
  and lifetime issues of dynamically allocated Py_buffer members (#9990)
  as well as crashes (#8305, #7433). Many new features have been added
  (See whatsnew/3.3), and the documentation has been updated extensively.
  The ndarray test object from _testbuffer.c implements all aspects of
  PEP-3118, so further development towards the complete implementation
  of the PEP can proceed in a test-driven manner.

  Thanks to Nick Coghlan, Antoine Pitrou and Pauli Virtanen for review
  and many ideas.

- Issue #12834: Fix incorrect results of memoryview.tobytes() for
  non-contiguous arrays.

- Issue #5231: Introduce memoryview.cast() method that allows changing
  format and shape without making a copy of the underlying memory.
diff --git a/Include/abstract.h b/Include/abstract.h
index 3946ec5..abb996f 100644
--- a/Include/abstract.h
+++ b/Include/abstract.h
@@ -559,7 +559,7 @@
     /* Copy the data from the src buffer to the buffer of destination
      */
 
-     PyAPI_FUNC(int) PyBuffer_IsContiguous(Py_buffer *view, char fort);
+     PyAPI_FUNC(int) PyBuffer_IsContiguous(const Py_buffer *view, char fort);
 
 
      PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int ndims,
diff --git a/Include/memoryobject.h b/Include/memoryobject.h
index aff5d99..4ac6f65 100644
--- a/Include/memoryobject.h
+++ b/Include/memoryobject.h
@@ -6,70 +6,64 @@
 extern "C" {
 #endif
 
+#ifndef Py_LIMITED_API
+PyAPI_DATA(PyTypeObject) _PyManagedBuffer_Type;
+#endif
 PyAPI_DATA(PyTypeObject) PyMemoryView_Type;
 
 #define PyMemoryView_Check(op) (Py_TYPE(op) == &PyMemoryView_Type)
 
 #ifndef Py_LIMITED_API
-/* Get a pointer to the underlying Py_buffer of a memoryview object. */
+/* Get a pointer to the memoryview's private copy of the exporter's buffer. */
 #define PyMemoryView_GET_BUFFER(op) (&((PyMemoryViewObject *)(op))->view)
-/* Get a pointer to the PyObject from which originates a memoryview object. */
+/* Get a pointer to the exporting object (this may be NULL!). */
 #define PyMemoryView_GET_BASE(op) (((PyMemoryViewObject *)(op))->view.obj)
 #endif
 
-
-PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, 
-						  int buffertype, 
-						  char fort);
-
-    /* Return a contiguous chunk of memory representing the buffer
-       from an object in a memory view object.  If a copy is made then the
-       base object for the memory view will be a *new* bytes object. 
-       
-       Otherwise, the base-object will be the object itself and no 
-       data-copying will be done. 
-
-       The buffertype argument can be PyBUF_READ, PyBUF_WRITE,
-       PyBUF_SHADOW to determine whether the returned buffer
-       should be READONLY, WRITABLE, or set to update the
-       original buffer if a copy must be made.  If buffertype is
-       PyBUF_WRITE and the buffer is not contiguous an error will
-       be raised.  In this circumstance, the user can use
-       PyBUF_SHADOW to ensure that a a writable temporary
-       contiguous buffer is returned.  The contents of this
-       contiguous buffer will be copied back into the original
-       object after the memoryview object is deleted as long as
-       the original object is writable and allows setting an
-       exclusive write lock. If this is not allowed by the
-       original object, then a BufferError is raised.
-       
-       If the object is multi-dimensional and if fortran is 'F',
-       the first dimension of the underlying array will vary the
-       fastest in the buffer.  If fortran is 'C', then the last
-       dimension will vary the fastest (C-style contiguous).  If
-       fortran is 'A', then it does not matter and you will get
-       whatever the object decides is more efficient.  
-
-       A new reference is returned that must be DECREF'd when finished.
-    */
-
 PyAPI_FUNC(PyObject *) PyMemoryView_FromObject(PyObject *base);
-
+PyAPI_FUNC(PyObject *) PyMemoryView_FromMemory(char *mem, Py_ssize_t size,
+                                               int flags);
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info);
-    /* create new if bufptr is NULL 
-        will be a new bytesobject in base */
 #endif
+PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base,
+                                                  int buffertype,
+                                                  char order);
 
 
-/* The struct is declared here so that macros can work, but it shouldn't
-   be considered public. Don't access those fields directly, use the macros
+/* The structs are declared here so that macros can work, but they shouldn't
+   be considered public. Don't access their fields directly, use the macros
    and functions instead! */
 #ifndef Py_LIMITED_API
+#define _Py_MANAGED_BUFFER_RELEASED    0x001  /* access to exporter blocked */
+#define _Py_MANAGED_BUFFER_FREE_FORMAT 0x002  /* free format */
 typedef struct {
     PyObject_HEAD
-    Py_buffer view;
-    Py_hash_t hash;
+    int flags;          /* state flags */
+    Py_ssize_t exports; /* number of direct memoryview exports */
+    Py_buffer master; /* snapshot buffer obtained from the original exporter */
+} _PyManagedBufferObject;
+
+
+/* static storage used for casting between formats */
+#define _Py_MEMORYVIEW_MAX_FORMAT 3 /* must be >= 3 */
+
+/* memoryview state flags */
+#define _Py_MEMORYVIEW_RELEASED    0x001  /* access to master buffer blocked */
+#define _Py_MEMORYVIEW_C           0x002  /* C-contiguous layout */
+#define _Py_MEMORYVIEW_FORTRAN     0x004  /* Fortran contiguous layout */
+#define _Py_MEMORYVIEW_SCALAR      0x008  /* scalar: ndim = 0 */
+#define _Py_MEMORYVIEW_PIL         0x010  /* PIL-style layout */
+
+typedef struct {
+    PyObject_VAR_HEAD
+    _PyManagedBufferObject *mbuf; /* managed buffer */
+    Py_hash_t hash;               /* hash value for read-only views */
+    int flags;                    /* state flags */
+    Py_ssize_t exports;           /* number of buffer re-exports */
+    Py_buffer view;               /* private copy of the exporter's view */
+    char format[_Py_MEMORYVIEW_MAX_FORMAT]; /* used for casting */
+    Py_ssize_t ob_array[1];       /* shape, strides, suboffsets */
 } PyMemoryViewObject;
 #endif
 
diff --git a/Include/object.h b/Include/object.h
index 71d9dc8..9b3055d 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -186,15 +186,16 @@
     Py_ssize_t *shape;
     Py_ssize_t *strides;
     Py_ssize_t *suboffsets;
-    Py_ssize_t smalltable[2];  /* static store for shape and strides of
-                                  mono-dimensional buffers. */
     void *internal;
 } Py_buffer;
 
 typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
 typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
 
-    /* Flags for getting buffers */
+/* Maximum number of dimensions */
+#define PyBUF_MAX_NDIM 64
+
+/* Flags for getting buffers */
 #define PyBUF_SIMPLE 0
 #define PyBUF_WRITABLE 0x0001
 /*  we used to include an E, backwards compatible alias  */