Attached patch defines a new type struct_timespec for the time module. A
new capsule exports the type along with to/from converters - opening a
bridge for C, and for example the datetime module.
Your comments welcomed. If people feel this is worth the effort and
going the right direction, I should be able to finish doco, unit-tests,
whatever else is missing with a bit of guidance and move on other
datetime aspects.
Regards,
Matthieu
diff -r 5754f069b123 Include/timemodule.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Include/timemodule.h Wed Dec 17 18:21:28 2014 -0800
@@ -0,0 +1,56 @@
+#ifndef Py_TIMEMODULE_H
+#define Py_TIMEMODULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+typedef struct timespec _PyTime_timespec;
+#else
+typedef struct {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+} _PyTime_timespec;
+#endif
+
+
+#define PyTime_CAPSULE_NAME "time._C_API"
+
+typedef struct {
+ PyTypeObject *StrucTimespecType;
+ PyObject *(*PyStructTimespecFromCStructTimespec)(_PyTime_timespec *);
+ int (*PyStructTimespecToCStructTimespec)(PyObject*, _PyTime_timespec *);
+} PyTime_C_API;
+
+
+#ifndef TIME_MODULE
+
+static PyTime_C_API *api = NULL;
+
+#define PyStructTimespecFromCStructTimespec \
+ api->PyStructTimespecFromCStructTimespec
+
+#define PyStructTimespecToCStructTimespec \
+ api->PyStructTimespecToCStructTimespec
+
+#define StructTimespec_Check(op) \
+ PyObject_TypeCheck(op, api->StrucTimespecType)
+
+#define StructTimespec_CheckExact(op) \
+ (Py_TYPE(op) == api->StrucTimespecType)
+
+static int
+import_time(void)
+{
+ api = (PyTime_C_API*)PyCapsule_Import(PyTime_CAPSULE_NAME, 0);
+ return (api != NULL) ? 0 : -1;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(Py_TIMEMODULE_H) */
+
diff -r 5754f069b123 Modules/timemodule.c
--- a/Modules/timemodule.c Sat Nov 22 12:54:57 2014 -0800
+++ b/Modules/timemodule.c Wed Dec 17 18:21:28 2014 -0800
@@ -30,6 +30,9 @@
#endif /* MS_WINDOWS */
#endif /* !__WATCOMC__ || __QNX__ */
+#define TIME_MODULE
+#include "timemodule.h"
+
/* Forward declarations */
static int floatsleep(double);
static PyObject* floattime(_Py_clock_info_t *info);
@@ -270,8 +273,25 @@
9,
};
+static PyStructSequence_Field struct_timespec_type_fields[] = {
+ {"tv_sec", "seconds"},
+ {"tv_nsec", "nanoseconds"},
+ {0}
+};
+
+static PyStructSequence_Desc struct_timespec_type_desc = {
+ "time.struct_timespec",
+ "POSIX.1b structure for a time value.",
+ struct_timespec_type_fields,
+ 2,
+};
+
+
static int initialized;
static PyTypeObject StructTimeType;
+static PyTypeObject StrucTimespecType;
+#define StructTimespec_Check(op) PyObject_TypeCheck(op, &StrucTimespecType)
+#define StructTimespec_CheckExact(op) (Py_TYPE(op) == &StrucTimespecType)
static PyObject *
@@ -1284,13 +1304,13 @@
PyDoc_STRVAR(module_doc,
"This module provides various functions to manipulate time values.\n\
\n\
-There are two standard representations of time. One is the number\n\
+There are three standard representations of time. One is the number\n\
of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
or a floating point number (to represent fractions of seconds).\n\
The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
The actual value can be retrieved by calling gmtime(0).\n\
\n\
-The other representation is a tuple of 9 integers giving local time.\n\
+Another representation is a tuple of 9 integers giving local time.\n\
The tuple items are:\n\
year (including century, e.g. 1998)\n\
month (1-12)\n\
@@ -1305,6 +1325,11 @@
if it is 1, the time is given in the DST time zone;\n\
if it is -1, mktime() should guess based on the date and time.\n\
\n\
+The other representation is a tuple of 2 integers similar to Posix.1b\n\
+struct timespec. The tuple items are:\n\
+ seconds\n\
+ nanoseconds (0-999999999)\n\
+\n\
Variables:\n\
\n\
timezone -- difference in seconds between UTC and local standard time\n\
@@ -1340,10 +1365,51 @@
NULL
};
+/*
+ * C API capsule
+ */
+
+static PyObject *
+PyStructTimespecFromCStructTimespec(_PyTime_timespec * ts)
+{
+ PyObject *v = PyStructSequence_New(&StrucTimespecType);
+ if (v == NULL)
+ return NULL;
+
+#define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
+ SET(0, ts->tv_sec);
+ SET(1, ts->tv_nsec);
+#undef SET
+ if (PyErr_Occurred()) {
+ Py_XDECREF(v);
+ return NULL;
+ }
+
+ return v;
+}
+
+int PyStructTimespecToCStructTimespec(PyObject* obj, _PyTime_timespec * ts)
+{
+
+ if (! StructTimespec_Check(obj))
+ return -1;
+
+ ts->tv_sec = PyLong_AsLong(PyStructSequence_GET_ITEM(obj,0));
+ ts->tv_nsec = PyLong_AsLong(PyStructSequence_GET_ITEM(obj,1));
+
+ return 0;
+}
+
+static PyTime_C_API api = {
+ &StrucTimespecType,
+ &PyStructTimespecFromCStructTimespec,
+ &PyStructTimespecToCStructTimespec
+};
+
PyMODINIT_FUNC
PyInit_time(void)
{
- PyObject *m;
+ PyObject *m, *c;
m = PyModule_Create(&timemodule);
if (m == NULL)
return NULL;
@@ -1355,14 +1421,25 @@
if (PyStructSequence_InitType2(&StructTimeType,
&struct_time_type_desc) < 0)
return NULL;
+ if (PyStructSequence_InitType2(&StrucTimespecType,
+ &struct_timespec_type_desc) < 0)
+ return NULL;
}
Py_INCREF(&StructTimeType);
+ Py_INCREF(&StrucTimespecType);
#ifdef HAVE_STRUCT_TM_TM_ZONE
PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 11);
#else
PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 9);
#endif
PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType);
+ PyModule_AddObject(m, "struct_timespec", (PyObject*) &StrucTimespecType);
+
+ c = PyCapsule_New(&api, PyTime_CAPSULE_NAME, NULL);
+ if (c == NULL)
+ return NULL;
+ PyModule_AddObject(m, "_C_API", c);
+
initialized = 1;
return m;
}
_______________________________________________
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com