mirror of
https://github.com/python/cpython
synced 2024-09-05 00:05:39 +00:00
gh-92869: ctypes: Add c_time_t (#92870)
Adds `ctypes.c_time_t` to represent the C `time_t` type accurately as its size varies. Primarily-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Gregory P. Smith <greg@krypto.org> [Google]
This commit is contained in:
parent
39c29f753e
commit
b296c7442b
|
@ -148,15 +148,14 @@ Calling functions
|
|||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can call these functions like any other Python callable. This example uses
|
||||
the ``time()`` function, which returns system time in seconds since the Unix
|
||||
epoch, and the ``GetModuleHandleA()`` function, which returns a win32 module
|
||||
handle.
|
||||
the ``rand()`` function, which takes no arguments and returns a pseudo-random integer::
|
||||
|
||||
This example calls both functions with a ``NULL`` pointer (``None`` should be used
|
||||
as the ``NULL`` pointer)::
|
||||
>>> print(libc.rand()) # doctest: +SKIP
|
||||
1804289383
|
||||
|
||||
On Windows, you can call the ``GetModuleHandleA()`` function, which returns a win32 module
|
||||
handle (passing ``None`` as single argument to call it with a ``NULL`` pointer)::
|
||||
|
||||
>>> print(libc.time(None)) # doctest: +SKIP
|
||||
1150640792
|
||||
>>> print(hex(windll.kernel32.GetModuleHandleA(None))) # doctest: +WINDOWS
|
||||
0x1d000000
|
||||
>>>
|
||||
|
@ -247,6 +246,8 @@ Fundamental data types
|
|||
| :class:`c_ssize_t` | :c:type:`ssize_t` or | int |
|
||||
| | :c:type:`Py_ssize_t` | |
|
||||
+----------------------+------------------------------------------+----------------------------+
|
||||
| :class:`c_time_t` | :c:type:`time_t` | int |
|
||||
+----------------------+------------------------------------------+----------------------------+
|
||||
| :class:`c_float` | :c:type:`float` | float |
|
||||
+----------------------+------------------------------------------+----------------------------+
|
||||
| :class:`c_double` | :c:type:`double` | float |
|
||||
|
@ -447,6 +448,21 @@ By default functions are assumed to return the C :c:type:`int` type. Other
|
|||
return types can be specified by setting the :attr:`restype` attribute of the
|
||||
function object.
|
||||
|
||||
The C prototype of ``time()`` is ``time_t time(time_t *)``. Because ``time_t``
|
||||
might be of a different type than the default return type ``int``, you should
|
||||
specify the ``restype``::
|
||||
|
||||
>>> libc.time.restype = c_time_t
|
||||
|
||||
The argument types can be specified using ``argtypes``::
|
||||
|
||||
>>> libc.time.argtypes = (POINTER(c_time_t),)
|
||||
|
||||
To call the function with a ``NULL`` pointer as first argument, use ``None``::
|
||||
|
||||
>>> print(libc.time(None)) # doctest: +SKIP
|
||||
1150640792
|
||||
|
||||
Here is a more advanced example, it uses the ``strchr`` function, which expects
|
||||
a string pointer and a char, and returns a pointer to a string::
|
||||
|
||||
|
@ -2275,6 +2291,13 @@ These are the fundamental ctypes data types:
|
|||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
.. class:: c_time_t
|
||||
|
||||
Represents the C :c:type:`time_t` datatype.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
.. class:: c_ubyte
|
||||
|
||||
Represents the C :c:type:`unsigned char` datatype, it interprets the value as
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
from _ctypes import __version__ as _ctypes_version
|
||||
from _ctypes import RTLD_LOCAL, RTLD_GLOBAL
|
||||
from _ctypes import ArgumentError
|
||||
from _ctypes import SIZEOF_TIME_T
|
||||
|
||||
from struct import calcsize as _calcsize
|
||||
|
||||
|
@ -563,4 +564,11 @@ def DllCanUnloadNow():
|
|||
elif sizeof(kind) == 8: c_uint64 = kind
|
||||
del(kind)
|
||||
|
||||
if SIZEOF_TIME_T == 8:
|
||||
c_time_t = c_int64
|
||||
elif SIZEOF_TIME_T == 4:
|
||||
c_time_t = c_int32
|
||||
else:
|
||||
raise SystemError(f"Unexpected sizeof(time_t): {SIZEOF_TIME_T=}")
|
||||
|
||||
_reset_cache()
|
||||
|
|
|
@ -28,6 +28,9 @@ def test_size_t(self):
|
|||
def test_ssize_t(self):
|
||||
self.assertEqual(sizeof(c_void_p), sizeof(c_ssize_t))
|
||||
|
||||
def test_time_t(self):
|
||||
self.assertEqual(sizeof(c_time_t), SIZEOF_TIME_T)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Added :class:`~ctypes.c_time_t` to :mod:`ctypes`, which has the same size as
|
||||
the :c:type:`time_t` type in C.
|
|
@ -5784,6 +5784,7 @@ _ctypes_add_objects(PyObject *mod)
|
|||
MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL));
|
||||
MOD_ADD("CTYPES_MAX_ARGCOUNT", PyLong_FromLong(CTYPES_MAX_ARGCOUNT));
|
||||
MOD_ADD("ArgumentError", Py_NewRef(PyExc_ArgError));
|
||||
MOD_ADD("SIZEOF_TIME_T", PyLong_FromSsize_t(SIZEOF_TIME_T));
|
||||
return 0;
|
||||
#undef MOD_ADD
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue