Skip to content

Commit dbb365d

Browse files
committed
Optimize reading of events
- Construct tuple directly instead of using Py_BuildValue. - Return a tuple of tuples instead of a list of tuples. - Read argument (fd) directly instead of using PyArg_ParseTuple.
1 parent cdb9c44 commit dbb365d

File tree

1 file changed

+17
-26
lines changed

1 file changed

+17
-26
lines changed

src/evdev/input.c

+17-26
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@ int test_bit(const char* bitmask, int bit) {
4646
static PyObject *
4747
device_read(PyObject *self, PyObject *args)
4848
{
49-
int fd;
5049
struct input_event event;
5150

5251
// get device file descriptor (O_RDONLY|O_NONBLOCK)
53-
if (PyArg_ParseTuple(args, "i", &fd) < 0)
54-
return NULL;
52+
int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
5553

5654
int n = read(fd, &event, sizeof(event));
5755

@@ -68,12 +66,9 @@ device_read(PyObject *self, PyObject *args)
6866
PyObject* sec = PyLong_FromLong(event.input_event_sec);
6967
PyObject* usec = PyLong_FromLong(event.input_event_usec);
7068
PyObject* val = PyLong_FromLong(event.value);
71-
PyObject* py_input_event = NULL;
72-
73-
py_input_event = Py_BuildValue("OOhhO", sec, usec, event.type, event.code, val);
74-
Py_DECREF(sec);
75-
Py_DECREF(usec);
76-
Py_DECREF(val);
69+
PyObject* type = PyLong_FromLong(event.type);
70+
PyObject* code = PyLong_FromLong(event.code);
71+
PyObject* py_input_event = PyTuple_Pack(5, sec, usec, type, code, val);
7772

7873
return py_input_event;
7974
}
@@ -83,17 +78,16 @@ device_read(PyObject *self, PyObject *args)
8378
static PyObject *
8479
device_read_many(PyObject *self, PyObject *args)
8580
{
86-
int fd;
87-
8881
// get device file descriptor (O_RDONLY|O_NONBLOCK)
89-
int ret = PyArg_ParseTuple(args, "i", &fd);
90-
if (!ret) return NULL;
82+
int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
9183

92-
PyObject* event_list = PyList_New(0);
9384
PyObject* py_input_event = NULL;
85+
PyObject* events = NULL;
9486
PyObject* sec = NULL;
9587
PyObject* usec = NULL;
9688
PyObject* val = NULL;
89+
PyObject* type = NULL;
90+
PyObject* code = NULL;
9791

9892
struct input_event event[64];
9993

@@ -102,26 +96,24 @@ device_read_many(PyObject *self, PyObject *args)
10296

10397
if (nread < 0) {
10498
PyErr_SetFromErrno(PyExc_OSError);
105-
Py_DECREF(event_list);
10699
return NULL;
107100
}
108101

109-
// Construct a list of event tuples, which we'll make sense of in Python
110-
for (unsigned i = 0 ; i < nread/event_size ; i++) {
102+
// Construct a tuple of event tuples. Each tuple is the arguments to InputEvent.
103+
size_t num_events = nread / event_size;
104+
events = PyTuple_New(num_events);
105+
for (size_t i = 0 ; i < num_events; i++) {
111106
sec = PyLong_FromLong(event[i].input_event_sec);
112107
usec = PyLong_FromLong(event[i].input_event_usec);
113108
val = PyLong_FromLong(event[i].value);
109+
type = PyLong_FromLong(event[i].type);
110+
code = PyLong_FromLong(event[i].code);
114111

115-
py_input_event = Py_BuildValue("OOhhO", sec, usec, event[i].type, event[i].code, val);
116-
PyList_Append(event_list, py_input_event);
117-
118-
Py_DECREF(py_input_event);
119-
Py_DECREF(sec);
120-
Py_DECREF(usec);
121-
Py_DECREF(val);
112+
py_input_event = PyTuple_Pack(5, sec, usec, type, code, val);
113+
PyTuple_SET_ITEM(events, i, py_input_event);
122114
}
123115

124-
return event_list;
116+
return events;
125117
}
126118

127119

@@ -539,7 +531,6 @@ ioctl_EVIOCGPROP(PyObject *self, PyObject *args)
539531
}
540532

541533

542-
543534
static PyMethodDef MethodTable[] = {
544535
{ "ioctl_devinfo", ioctl_devinfo, METH_VARARGS, "fetch input device info" },
545536
{ "ioctl_capabilities", ioctl_capabilities, METH_VARARGS, "fetch input device capabilities" },

0 commit comments

Comments
 (0)