Repository: MatthieuDartiailh/pyclibrary

Issue:
Support for size_t
The standard C types like uint64_t are apparently supported out of the box by pyclibrary, but not size_t.

Workarounds for a 64bit DLL:

```
parser.add_def("types", "size_t", pyclibrary.c_parser.Type("uint64_t"))
````

or use the "replace" option of the Parser class to map it to "uint64_t":
```
replace = {
       "\\bsize_t\\b": "uint64_t",
    })
```

Would it be possible to support size_t natively ?

Discussion:

Solution patch:
diff --git a/pyclibrary/backends/ctypes.py b/pyclibrary/backends/ctypes.py
index c5955a8..bbff66c 100644
--- a/pyclibrary/backends/ctypes.py
+++ b/pyclibrary/backends/ctypes.py
@@ -34,6 +34,8 @@ from ctypes import (
     c_longdouble,
     c_longlong,
     c_short,
+    c_size_t,
+    c_ssize_t,
     c_ubyte,
     c_uint,
     c_uint8,
@@ -55,6 +57,9 @@ from inspect import cleandoc
 if sys.platform == "win32":
     from ctypes import HRESULT, WINFUNCTYPE, oledll, windll
 
+if sys.version_info >= (3, 12):
+    from ctypes import c_time_t
+
 from ..c_library import CLibrary
 from ..errors import DefinitionError
 from ..utils import find_library
@@ -425,6 +430,8 @@ def init_clibrary(extra_types={}):
         "int32_t": c_int32,
         "uint64_t": c_uint64,
         "int64_t": c_int64,
+        "size_t": c_size_t,
+        "ssize_t": c_ssize_t,
     }
 
     if sys.platform == "win32":
@@ -432,6 +439,9 @@ def init_clibrary(extra_types={}):
             if k in WIN_TYPES:
                 extra_types[k] = WIN_TYPES[k]
 
+    if sys.version_info >= (3, 12):
+        extra_types['time_t'] = c_time_t
+
     # Now complete the list with some more exotic types
     CTypesCLibrary._types_.update(extra_types)
 
diff --git a/pyclibrary/c_parser.py b/pyclibrary/c_parser.py
index 902eec1..28f7fac 100644
--- a/pyclibrary/c_parser.py
+++ b/pyclibrary/c_parser.py
@@ -1481,7 +1481,10 @@ class CParser(object):
                         break
                     n += 1
             else:
-                name = t.name[0]
+                if isinstance(t.name, str):
+                    name = t.name
+                else:
+                    name = t.name[0]
 
             logger.debug("  name: {}".format(name))
 


Test patch:
diff --git a/tests/headers/enums.h b/tests/headers/enums.h
index a418b04..7584189 100644
--- a/tests/headers/enums.h
+++ b/tests/headers/enums.h
@@ -22,3 +22,5 @@ typedef enum
     typedef_enum1 = 1,
     typedef_enum2
 } no_name_enum_typeddef;
+
+void function_taking_enum(enum enum_name e);
diff --git a/tests/headers/variables.h b/tests/headers/variables.h
index 0567aa7..04fa4bb 100644
--- a/tests/headers/variables.h
+++ b/tests/headers/variables.h
@@ -22,6 +22,10 @@ long long int long_long_int = 1;
 unsigned long long long_long_un = 1;
 unsigned long long int long_long_int_un = 1;
 
+// stddef integers
+size_t size = 1;
+ssize_t ssize = 1;
+
 // C99 integers
 int8_t i8 = 1;
 int16_t i16 = 1;
@@ -60,6 +64,9 @@ int x2 = (typeCast)0x544 <<16;
 float array[2] = {0x1, 3.1415e6};
 static const int * const (**intJunk[4]);
 
+// time_t
+time_t time = 1;
+
 const int * volatile * typeQualedIntPtrPtr, volatile * typeQualedIntPtr;
 
 // Test type definition precedence
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 619d942..cc22b4c 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -563,6 +563,16 @@ class TestParsing(object):
             Type("unsigned long " "long int"),
         )
 
+        # stddef integers
+        assert "size" in variables and variables["size"] == (
+            1,
+            Type("size_t"),
+        )
+        assert "ssize" in variables and variables["ssize"] == (
+            1,
+            Type("ssize_t"),
+        )
+
         # C99 integers
         for i in (8, 16, 32, 64):
             assert "i%d" % i in variables and variables["i%d" % i] == (
@@ -638,6 +648,13 @@ class TestParsing(object):
             ),
         )
 
+        # time_t
+        if sys.version_info >= (3, 12):
+            assert "time" in variables and variables["time"] == (
+                1,
+                Type("time_t"),
+            )
+
         # test type qualifiers
         assert variables.get("typeQualedIntPtrPtr") == (
             None,
@@ -719,6 +736,7 @@ class TestParsing(object):
         enums = self.parser.defs["enums"]
         types = self.parser.defs["types"]
         variables = self.parser.defs["variables"]
+        functions = self.parser.defs["functions"]
         print(self.parser.defs["values"])
         assert "enum_name" in enums and "enum enum_name" in types
         assert enums["enum_name"] == {"enum1": 129, "enum2": 6, "enum3": 7, "enum4": 8}
@@ -737,6 +755,11 @@ class TestParsing(object):
         assert "anon_enum1" in enums
         assert "no_name_enum_typeddef" in types
 
+        assert "function_taking_enum" in functions
+        assert functions["function_taking_enum"] == Type(
+            Type("void"), (("e", Type("enum enum_name"), None),)
+        )
+
     def test_struct(self):
         path = os.path.join(self.h_dir, "structs.h")
         self.parser.load_file(path)