Commits

Armin Rigo  committed 761b49f

Support for "typedef ... *foo_p".

  • Participants
  • Parent commits 2df9a7b

Comments (0)

Files changed (4)

File cffi/cparser.py

                 if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
                         and decl.type.type.names == ['__dotdotdot__']):
                     realtype = model.unknown_type(decl.name)
+                elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
+                      isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
+                      isinstance(decl.type.type.type,
+                                 pycparser.c_ast.IdentifierType) and
+                      decl.type.type.type.names == ['__dotdotdot__']):
+                    realtype = model.unknown_ptr_type(decl.name)
                 else:
                     realtype = self._get_type(decl.type, name=decl.name)
                 self._declare('typedef ' + decl.name, realtype)

File cffi/model.py

         return BPtr
 
 
+class NamedPointerType(PointerType):
+    _attrs_ = ('totype', 'name')
+
+    def __init__(self, totype, name):
+        PointerType.__init__(self, totype)
+        self.name = name
+
+    def _get_c_name(self, replace_with):
+        return self.name + replace_with
+
+
 class ArrayType(BaseType):
     _attrs_ = ('item', 'length')
 
     tp.forcename = name
     return tp
 
+def unknown_ptr_type(name):
+    tp = StructType('*$%s' % name, None, None, None)
+    return NamedPointerType(tp, name)
+
 def global_cache(ffi, funcname, *args):
     try:
         return ffi._backend.__typecache[args]

File doc/source/index.rst

 
 *  unknown types: the syntax "``typedef ... foo_t;``" declares the type
    ``foo_t`` as opaque.  Useful mainly for when the API takes and returns
-   ``foo_t *`` without you needing to look inside the ``foo_t``.  Note that
+   ``foo_t *`` without you needing to look inside the ``foo_t``.  Also
+   works with "``typedef ... *foo_p;``" which declares the pointer type
+   ``foo_p`` without giving a name to the opaque type itself.  Note that
    such an opaque struct has no known size, which prevents some operations
    from working (mostly like in C).  In some cases you need to say that
    ``foo_t`` is not opaque, but you just don't know any field in it; then

File testing/test_verify.py

     lib = ffi.verify("typedef struct token_s token_t;")
     # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
 
+def test_unknown_type_3():
+    ffi = FFI()
+    ffi.cdef("""
+        typedef ... *token_p;
+        token_p foo(token_p);
+    """)
+    lib = ffi.verify("""
+        typedef struct _token_s *token_p;
+        token_p foo(token_p arg) {
+            if (arg)
+                return (token_p)0x12347;
+            else
+                return (token_p)0x12345;
+        }
+    """)
+    p = lib.foo(ffi.NULL)
+    assert int(ffi.cast("intptr_t", p)) == 0x12345
+    q = lib.foo(p)
+    assert int(ffi.cast("intptr_t", q)) == 0x12347
+
 def test_varargs():
     ffi = FFI()
     ffi.cdef("int foo(int x, ...);")