[pypy-svn] r23862 - pypy/dist/pypy/doc

arigo at codespeak.net arigo at codespeak.net
Wed Mar 1 19:58:37 CET 2006

Author: arigo
Date: Wed Mar  1 19:58:26 2006
New Revision: 23862

Reworking the memory layout section of the rctypes document.

Modified: pypy/dist/pypy/doc/ctypes-integration.txt
--- pypy/dist/pypy/doc/ctypes-integration.txt	(original)
+++ pypy/dist/pypy/doc/ctypes-integration.txt	Wed Mar  1 19:58:26 2006
@@ -80,46 +80,103 @@
+In Ctypes, all instances are mutable boxes containing either some raw
+memory with a layout compatible to that of the equivalent C type, or a
+reference to such memory.  The reference indirection is transparent to
+the user; for example, dereferencing a ctypes object "pointer to
+structure" results in a "structure" object that doesn't include a copy
+of the data, but only a reference to that data.  (This is similar to the
+C++ notion of reference: it is just a pointer at the machine level, but
+at the language level it behaves like the object that it points to, not
+like a pointer.)
+We map this to the LLType model as follows.  For boxes that embed the
+raw memory content::
+    Ptr( GcStruct( "name",
+           ("c_data", Struct(...) ) ) )
+where the raw memory content and layout is specified by the
+"Struct(...)" part.
+For boxes that don't embed the raw memory content::
+    Ptr( GcStruct( "name",
+           ("c_data_ref", Ptr(Struct(...)) ) ) )
+In both cases, the outer GcStruct is needed to make the boxes tracked by
+the GC automatically.  The "c_data" or "c_data_ref" field either embeds
+or references the raw memory; the "Struct(...)" definition specifies the
+exact C layout expected for that memory.
+Of course, the "c_data" and "c_data_ref" fields are not visible to the
+rpython-level user.  This is where an rctype-specific restriction comes
+from: it must be possible for the annotator to figure out statically for
+each variable if it needs to be implemented with a "c_data" or a
+"c_data_ref" field.  (The annotation SomeCTypesObject contains a
+memorystate field which can be OWNSMEMORY ("c_data" case) or MEMORYALIAS
+("c_data_ref" case).)
 Primitive Types
+Ctypes' primitive types are mapped directly to the correspondending PyPy
+LLType: Signed, Float, etc.  Primitive values can always be copied around,
+so there is no needed for the "c_data_ref" case here.  We get::
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data"
+                    (Struct "C_Data_<TypeName>
+                            ( "value", Signed/Float/etc. ) ) ) ) )
+Note that we don't make "c_data" itself a Signed or Float directly because
+in LLType we can't take pointers to Signed or Float, only to Struct or
+A C pointer behaves like a primitive value, in that it can be copied
+around.  We get::
-Ctypes' primitive types are mapped directly to the correspondending
-PyPy type.
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data"
+                    (Struct "C_Data_<TypeName>
+                            ( "value", Ptr(...) ) ) ) ) )
+However, there is a special case here: the pointer might point to data
+owned by another CtypesBox -- i.e. it can point to the "c_data" field of
+some other CtypesBox.  In this case we must make sure that the other
+CtypesBox stays alive.  This is done by adding an extra field
+referencing the gc box (this field is not otherwise used)::
+    Ptr( GcStruct( "CtypesBox_<TypeName>
+            ( "c_data"
+                    (Struct "C_Data_<TypeName>
+                            ( "value", Ptr(...) ) ) )
+            ( "keepalive"
+                    (Ptr(GcStruct("CtypesBox_<TargetTypeName>"))) ) ) )
-Structures will have the following memory layout if they were allocated by ctypes::
+Structures will have the following memory layout (owning their raw memory)
+if they were allocated by ctypes::
-    Ptr( GcStruct( "CtypesGcStructure_<ClassName> 
+    Ptr( GcStruct( "CtypesBox_<StructName>
             ( "c_data" 
-                    (Struct "C-Data_<ClassName>
+                    (Struct "C_Data_<StructName>
                             *<Fieldefintions>) ) ) )
-We will try hard not to expose the "c-data" member of the structure
-at rpython level.
-Structures that result form dereferencing a pointer will have the following
-    Ptr( GcStruct( "CtypesStructure_<ClassName>
-        ( "c_data"
-                Ptr( Struct( "C-Data_<ClassName>
-                             *<Fieldefintions>) ) ) ) )
-Pointers pointing to structures allocated by ctypes will have the following memory layout::
-    Ptr( GcStruct( "CtypesGCPointer_<ClassName>
-        "contents" Ptr( GcStruct( "CtypesGcStructure_<Name>" ... ) ) ) )
-Pointers pointing returned from external functions have the follwing layout if the
-point to a structure::
-    Ptr( GcStruct( "CtypesPointer_<ClassName>"
-        "contents" Ptr( Struct( "CtypesStructure_<Name>" ... ) ) ) )
+For structures obtained by dereferencing a pointer (by reading its
+"contents" attribute), the structure box does not own the memory::
-Currently it is not decided whether assiging a pointers `contents` attribute from
-a GC-pointer should be allowed. The other case will only become valid if we implement
-structures with mixed memory state.
+    Ptr( GcStruct( "CtypesBox_<StructName>
+            ( "c_data_ref" 
+                    (Ptr(Struct "C_Data_<StructName>
+                            *<Fieldefintions>) ) ) ) )
+One or several Keepalive fields might be necessary in each case.
+(To be clarified...)
+Arrays behave like structures, but use an Array instead of a Struct in
+the "c_data" or "c_data_ref" declaration.

More information about the Pypy-commit mailing list