2 * This file is part of the libsigrok project.
4 * Copyright (C) 2014 Martin Ling <martin-sigrok@earth.li>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 "@mainpage API Reference
26 The pysigrok API provides an object-oriented Python interface to the
27 functionality in libsigrok. It is built on top of the libsigrokcxx C++ API.
32 Usage of the pysigrok API needs to begin with a call to Context.create().
33 This will create the global libsigrok context and returns a Context object.
34 Methods on this object provide access to the hardware drivers, input and output
35 formats supported by the library, as well as means of creating other objects
36 such as sessions and triggers.
41 When any libsigrok C API call returns an error, an Error exception is raised,
42 which provides access to the error code and description."
45 %module(docstring=DOCSTRING) classes
48 #include <pygobject.h>
49 #include <numpy/arrayobject.h>
52 PyTypeObject *IOChannel;
57 #if PYGOBJECT_FLAGS_SIGNED
58 typedef gint pyg_flags_type;
60 typedef guint pyg_flags_type;
66 pygobject_init(-1, -1, -1);
67 GLib = PyImport_ImportModule("gi.repository.GLib");
68 IOChannel = (PyTypeObject *) PyObject_GetAttrString(GLib, "IOChannel");
69 PollFD = (PyTypeObject *) PyObject_GetAttrString(GLib, "PollFD");
73 /* Map file objects to file descriptors. */
74 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
75 $1 = (PyObject_AsFileDescriptor($input) != -1);
79 int fd = PyObject_AsFileDescriptor($input);
81 SWIG_exception(SWIG_TypeError,
82 "Expected file object or integer file descriptor");
87 /* Map from Glib::Variant to native Python types. */
88 %typemap(out) Glib::VariantBase {
89 GValue *value = g_new0(GValue, 1);
90 g_value_init(value, G_TYPE_VARIANT);
91 g_value_set_variant(value, $1.gobj());
92 PyObject *variant = pyg_value_as_pyobject(value, true);
93 $result = PyObject_CallMethod(variant,
94 const_cast<char *>("unpack"),
95 const_cast<char *>(""), NULL);
100 /* Map from Glib::IOCondition to GLib.IOCondition. */
101 %typecheck(SWIG_TYPECHECK_POINTER) Glib::IOCondition {
102 pyg_flags_type flags;
103 $1 = pygobject_check($input, &PyGFlags_Type) &&
104 (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) != -1);
107 %typemap(in) Glib::IOCondition {
108 if (!pygobject_check($input, &PyGFlags_Type))
109 SWIG_exception(SWIG_TypeError, "Expected GLib.IOCondition value");
110 pyg_flags_type flags;
111 if (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) == -1)
112 SWIG_exception(SWIG_TypeError, "Not a valid Glib.IOCondition value");
113 $1 = (Glib::IOCondition) flags;
117 %typemap(out) Glib::IOCondition {
118 GValue *value = g_new0(GValue, 1);
119 g_value_init(value, G_TYPE_IO_CONDITION);
120 g_value_set_flags(value, &$1);
121 $result = pyg_value_as_pyobject(value, true);
125 /* Map from GLib.PollFD to Glib::PollFD *. */
126 %typecheck(SWIG_TYPECHECK_POINTER) Glib::PollFD {
127 $1 = pygobject_check($input, PollFD);
130 %typemap(in) Glib::PollFD {
131 if (!pygobject_check($input, PollFD))
132 SWIG_exception(SWIG_TypeError, "Expected GLib.PollFD");
133 PyObject *fd_obj = PyObject_GetAttrString($input, "fd");
134 PyObject *events_obj = PyObject_GetAttrString($input, "events");
135 pyg_flags_type flags;
136 pyg_flags_get_value(G_TYPE_IO_CONDITION, events_obj, &flags);
137 int fd = PyInt_AsLong(fd_obj);
138 Glib::IOCondition events = (Glib::IOCondition) flags;
139 $1 = Glib::PollFD(fd, events);
142 /* Map from GLib.IOChannel to Glib::IOChannel *. */
143 %typecheck(SWIG_TYPECHECK_POINTER) Glib::RefPtr<Glib::IOChannel> {
144 $1 = pygobject_check($input, IOChannel);
147 %typemap(in) Glib::RefPtr<Glib::IOChannel> {
148 if (!pygobject_check($input, IOChannel))
149 SWIG_exception(SWIG_TypeError, "Expected GLib.IOChannel");
150 $1 = Glib::wrap((GIOChannel *) PyObject_Hash($input), true);
153 /* Map from callable PyObject to SourceCallbackFunction. */
154 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SourceCallbackFunction {
155 $1 = PyCallable_Check($input);
158 %typemap(in) sigrok::SourceCallbackFunction {
159 if (!PyCallable_Check($input))
160 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
162 $1 = [=] (Glib::IOCondition revents) {
163 auto gstate = PyGILState_Ensure();
165 GValue *value = g_new0(GValue, 1);
166 g_value_init(value, G_TYPE_IO_CONDITION);
167 g_value_set_flags(value, revents);
168 auto revents_obj = pyg_value_as_pyobject(value, true);
171 auto arglist = Py_BuildValue("(O)", revents_obj);
173 auto result = PyEval_CallObject($input, arglist);
176 Py_XDECREF(revents_obj);
178 bool completed = !PyErr_Occurred();
183 bool valid_result = (completed && PyBool_Check(result));
185 if (completed && !valid_result)
187 PyErr_SetString(PyExc_TypeError,
188 "EventSource callback did not return a boolean");
192 bool retval = (valid_result && result == Py_True);
196 PyGILState_Release(gstate);
199 throw sigrok::Error(SR_ERR);
207 /* Map from callable PyObject to LogCallbackFunction */
208 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
209 $1 = PyCallable_Check($input);
212 %typemap(in) sigrok::LogCallbackFunction {
213 if (!PyCallable_Check($input))
214 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
216 $1 = [=] (const sigrok::LogLevel *loglevel, string message) {
217 auto gstate = PyGILState_Ensure();
219 auto log_obj = SWIG_NewPointerObj(
220 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
222 auto string_obj = PyString_FromString(message.c_str());
224 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
226 auto result = PyEval_CallObject($input, arglist);
230 Py_XDECREF(string_obj);
232 bool completed = !PyErr_Occurred();
237 bool valid_result = (completed && result == Py_None);
241 if (completed && !valid_result)
243 PyErr_SetString(PyExc_TypeError,
244 "Log callback did not return None");
248 PyGILState_Release(gstate);
251 throw sigrok::Error(SR_ERR);
257 /* Map from callable PyObject to DatafeedCallbackFunction */
258 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
259 $1 = PyCallable_Check($input);
262 %typemap(in) sigrok::DatafeedCallbackFunction {
263 if (!PyCallable_Check($input))
264 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
266 $1 = [=] (std::shared_ptr<sigrok::Device> device,
267 std::shared_ptr<sigrok::Packet> packet) {
268 auto gstate = PyGILState_Ensure();
270 auto device_obj = SWIG_NewPointerObj(
271 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
272 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
274 auto packet_obj = SWIG_NewPointerObj(
275 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
276 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
278 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
280 auto result = PyEval_CallObject($input, arglist);
283 Py_XDECREF(device_obj);
284 Py_XDECREF(packet_obj);
286 bool completed = !PyErr_Occurred();
291 bool valid_result = (completed && result == Py_None);
295 if (completed && !valid_result)
297 PyErr_SetString(PyExc_TypeError,
298 "Datafeed callback did not return None");
302 PyGILState_Release(gstate);
305 throw sigrok::Error(SR_ERR);
311 /* Cast PacketPayload pointers to correct subclass type. */
312 %ignore sigrok::Packet::payload;
314 %extend sigrok::Packet
316 std::shared_ptr<sigrok::Header> _payload_header()
318 return dynamic_pointer_cast<sigrok::Header>($self->payload());
320 std::shared_ptr<sigrok::Meta> _payload_meta()
322 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
324 std::shared_ptr<sigrok::Analog> _payload_analog()
326 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
328 std::shared_ptr<sigrok::Logic> _payload_logic()
330 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
334 %extend sigrok::Packet
339 if self.type == PacketType.HEADER:
340 return self._payload_header()
341 elif self.type == PacketType.META:
342 return self._payload_meta()
343 elif self.type == PacketType.LOGIC:
344 return self._payload_logic()
345 elif self.type == PacketType.ANALOG:
346 return self._payload_analog()
350 payload = property(_payload)
356 #include "libsigrokcxx/libsigrokcxx.hpp"
358 /* Convert from a Python dict to a std::map<std::string, std::string> */
359 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
361 if (!PyDict_Check(dict))
362 throw sigrok::Error(SR_ERR_ARG);
364 std::map<std::string, std::string> output;
366 PyObject *py_key, *py_value;
369 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
370 if (!PyString_Check(py_key))
371 throw sigrok::Error(SR_ERR_ARG);
372 if (!PyString_Check(py_value))
373 throw sigrok::Error(SR_ERR_ARG);
374 auto key = PyString_AsString(py_key);
375 auto value = PyString_AsString(py_value);
382 /* Convert from a Python type to Glib::Variant, according to config key data type. */
383 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
385 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
387 if (type == SR_T_UINT64 && PyInt_Check(input))
388 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
389 if (type == SR_T_UINT64 && PyLong_Check(input))
390 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
391 else if (type == SR_T_STRING && PyString_Check(input))
392 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
393 else if (type == SR_T_BOOL && PyBool_Check(input))
394 return Glib::Variant<bool>::create(input == Py_True);
395 else if (type == SR_T_FLOAT && PyFloat_Check(input))
396 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
397 else if (type == SR_T_INT32 && PyInt_Check(input))
398 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
400 throw sigrok::Error(SR_ERR_ARG);
403 /* Convert from a Python type to Glib::Variant, according to Option data type. */
404 Glib::VariantBase python_to_variant_by_option(PyObject *input,
405 std::shared_ptr<sigrok::Option> option)
407 GVariantType *type = option->default_value().get_type().gobj();
409 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
410 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
411 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
412 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
413 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
414 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
415 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
416 return Glib::Variant<bool>::create(input == Py_True);
417 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
418 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
419 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
420 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
422 throw sigrok::Error(SR_ERR_ARG);
425 /* Convert from a Python dict to a std::map<std::string, std::string> */
426 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
427 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
429 if (!PyDict_Check(dict))
430 throw sigrok::Error(SR_ERR_ARG);
432 std::map<std::string, Glib::VariantBase> output;
434 PyObject *py_key, *py_value;
437 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
438 if (!PyString_Check(py_key))
439 throw sigrok::Error(SR_ERR_ARG);
440 auto key = PyString_AsString(py_key);
441 auto value = python_to_variant_by_option(py_value, options[key]);
450 /* Ignore these methods, we will override them below. */
451 %ignore sigrok::Analog::data;
452 %ignore sigrok::Driver::scan;
453 %ignore sigrok::InputFormat::create_input;
454 %ignore sigrok::OutputFormat::create_output;
458 %define %attributevector(Class, Type, Name, Get)
459 %rename(_ ## Get) sigrok::Class::Get;
460 %extend sigrok::Class
464 Name = property(_ ## Get)
469 %define %attributemap(Class, Type, Name, Get)
470 %rename(_ ## Get) sigrok::Class::Get;
471 %extend sigrok::Class
475 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
480 %define %enumextras(Class)
481 %extend sigrok::Class
490 def __eq__(self, other):
491 return (type(self) is type(other) and hash(self) == hash(other))
493 def __ne__(self, other):
494 return (type(self) is not type(other) or hash(self) != hash(other))
499 %include "../../../swig/classes.i"
501 /* Support Driver.scan() with keyword arguments. */
502 %extend sigrok::Driver
504 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
506 if (!PyDict_Check(dict))
507 throw sigrok::Error(SR_ERR_ARG);
509 PyObject *py_key, *py_value;
511 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
513 while (PyDict_Next(dict, &pos, &py_key, &py_value))
515 if (!PyString_Check(py_key))
516 throw sigrok::Error(SR_ERR_ARG);
517 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
518 auto value = python_to_variant_by_key(py_value, key);
519 options[key] = value;
522 return $self->scan(options);
528 def _Driver_scan(self, **kwargs):
529 return self._scan_kwargs(kwargs)
531 Driver.scan = _Driver_scan
534 /* Support InputFormat.create_input() with keyword arguments. */
535 %extend sigrok::InputFormat
537 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
539 return $self->create_input(
540 dict_to_map_options(dict, $self->options()));
546 def _InputFormat_create_input(self, **kwargs):
547 return self._create_input(kwargs)
549 InputFormat.create_input = _InputFormat_create_input
552 /* Support OutputFormat.create_output() with keyword arguments. */
553 %extend sigrok::OutputFormat
555 std::shared_ptr<sigrok::Output> _create_output_kwargs(
556 std::shared_ptr<sigrok::Device> device, PyObject *dict)
558 return $self->create_output(device,
559 dict_to_map_options(dict, $self->options()));
565 def _OutputFormat_create_output(self, device, **kwargs):
566 return self._create_output_kwargs(device, kwargs)
568 OutputFormat.create_output = _OutputFormat_create_output
571 /* Support config_set() with Python input types. */
572 %extend sigrok::Configurable
574 void config_set(const ConfigKey *key, PyObject *input)
576 $self->config_set(key, python_to_variant_by_key(input, key));
580 /* Return NumPy array from Analog::data(). */
581 %extend sigrok::Analog
587 dims[0] = $self->channels().size();
588 dims[1] = $self->num_samples();
589 int typenum = NPY_FLOAT;
590 void *data = $self->data_pointer();
591 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
596 data = property(_data)