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 sigrok++ 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>
51 PyTypeObject *IOChannel;
56 #if PYGOBJECT_FLAGS_SIGNED
57 typedef gint pyg_flags_type;
59 typedef guint pyg_flags_type;
65 pygobject_init(-1, -1, -1);
66 GLib = PyImport_ImportModule("gi.repository.GLib");
67 IOChannel = (PyTypeObject *) PyObject_GetAttrString(GLib, "IOChannel");
68 PollFD = (PyTypeObject *) PyObject_GetAttrString(GLib, "PollFD");
71 /* Map file objects to file descriptors. */
72 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
73 $1 = (PyObject_AsFileDescriptor($input) != -1);
77 int fd = PyObject_AsFileDescriptor($input);
79 SWIG_exception(SWIG_TypeError,
80 "Expected file object or integer file descriptor");
85 /* Map from Glib::Variant to native Python types. */
86 %typemap(out) Glib::VariantBase {
87 GValue *value = g_new0(GValue, 1);
88 g_value_init(value, G_TYPE_VARIANT);
89 g_value_set_variant(value, $1.gobj());
90 PyObject *variant = pyg_value_as_pyobject(value, true);
91 $result = PyObject_CallMethod(variant,
92 const_cast<char *>("unpack"),
93 const_cast<char *>(""), NULL);
98 /* Map from Glib::IOCondition to GLib.IOCondition. */
99 %typecheck(SWIG_TYPECHECK_POINTER) Glib::IOCondition {
100 pyg_flags_type flags;
101 $1 = pygobject_check($input, &PyGFlags_Type) &&
102 (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) != -1);
105 %typemap(in) Glib::IOCondition {
106 if (!pygobject_check($input, &PyGFlags_Type))
107 SWIG_exception(SWIG_TypeError, "Expected GLib.IOCondition value");
108 pyg_flags_type flags;
109 if (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) == -1)
110 SWIG_exception(SWIG_TypeError, "Not a valid Glib.IOCondition value");
111 $1 = (Glib::IOCondition) flags;
115 %typemap(out) Glib::IOCondition {
116 GValue *value = g_new0(GValue, 1);
117 g_value_init(value, G_TYPE_IO_CONDITION);
118 g_value_set_flags(value, &$1);
119 $result = pyg_value_as_pyobject(value, true);
123 /* Map from GLib.PollFD to Glib::PollFD *. */
124 %typecheck(SWIG_TYPECHECK_POINTER) Glib::PollFD {
125 $1 = pygobject_check($input, PollFD);
128 %typemap(in) Glib::PollFD {
129 if (!pygobject_check($input, PollFD))
130 SWIG_exception(SWIG_TypeError, "Expected GLib.PollFD");
131 PyObject *fd_obj = PyObject_GetAttrString($input, "fd");
132 PyObject *events_obj = PyObject_GetAttrString($input, "events");
133 pyg_flags_type flags;
134 pyg_flags_get_value(G_TYPE_IO_CONDITION, events_obj, &flags);
135 int fd = PyInt_AsLong(fd_obj);
136 Glib::IOCondition events = (Glib::IOCondition) flags;
137 $1 = Glib::PollFD(fd, events);
140 /* Map from GLib.IOChannel to Glib::IOChannel *. */
141 %typecheck(SWIG_TYPECHECK_POINTER) Glib::RefPtr<Glib::IOChannel> {
142 $1 = pygobject_check($input, IOChannel);
145 %typemap(in) Glib::RefPtr<Glib::IOChannel> {
146 if (!pygobject_check($input, IOChannel))
147 SWIG_exception(SWIG_TypeError, "Expected GLib.IOChannel");
148 $1 = Glib::wrap((GIOChannel *) PyObject_Hash($input), true);
151 /* Map from callable PyObject to SourceCallbackFunction. */
152 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SourceCallbackFunction {
153 $1 = PyCallable_Check($input);
156 %typemap(in) sigrok::SourceCallbackFunction {
157 if (!PyCallable_Check($input))
158 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
160 $1 = [=] (Glib::IOCondition revents) {
161 auto gstate = PyGILState_Ensure();
163 GValue *value = g_new0(GValue, 1);
164 g_value_init(value, G_TYPE_IO_CONDITION);
165 g_value_set_flags(value, revents);
166 auto revents_obj = pyg_value_as_pyobject(value, true);
169 auto arglist = Py_BuildValue("(O)", revents_obj);
171 auto result = PyEval_CallObject($input, arglist);
174 Py_XDECREF(revents_obj);
176 bool completed = !PyErr_Occurred();
181 bool valid_result = (completed && PyBool_Check(result));
183 if (completed && !valid_result)
185 PyErr_SetString(PyExc_TypeError,
186 "EventSource callback did not return a boolean");
190 bool retval = (valid_result && result == Py_True);
194 PyGILState_Release(gstate);
197 throw sigrok::Error(SR_ERR);
205 /* Map from callable PyObject to LogCallbackFunction */
206 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
207 $1 = PyCallable_Check($input);
210 %typemap(in) sigrok::LogCallbackFunction {
211 if (!PyCallable_Check($input))
212 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
214 $1 = [=] (const sigrok::LogLevel *loglevel, string message) {
215 auto gstate = PyGILState_Ensure();
217 auto log_obj = SWIG_NewPointerObj(
218 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
220 auto string_obj = PyString_FromString(message.c_str());
222 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
224 auto result = PyEval_CallObject($input, arglist);
228 Py_XDECREF(string_obj);
230 bool completed = !PyErr_Occurred();
235 bool valid_result = (completed && result == Py_None);
239 if (completed && !valid_result)
241 PyErr_SetString(PyExc_TypeError,
242 "Log callback did not return None");
246 PyGILState_Release(gstate);
249 throw sigrok::Error(SR_ERR);
255 /* Map from callable PyObject to DatafeedCallbackFunction */
256 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
257 $1 = PyCallable_Check($input);
260 %typemap(in) sigrok::DatafeedCallbackFunction {
261 if (!PyCallable_Check($input))
262 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
264 $1 = [=] (std::shared_ptr<sigrok::Device> device,
265 std::shared_ptr<sigrok::Packet> packet) {
266 auto gstate = PyGILState_Ensure();
268 auto device_obj = SWIG_NewPointerObj(
269 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
270 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
272 auto packet_obj = SWIG_NewPointerObj(
273 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
274 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
276 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
278 auto result = PyEval_CallObject($input, arglist);
281 Py_XDECREF(device_obj);
282 Py_XDECREF(packet_obj);
284 bool completed = !PyErr_Occurred();
289 bool valid_result = (completed && result == Py_None);
293 if (completed && !valid_result)
295 PyErr_SetString(PyExc_TypeError,
296 "Datafeed callback did not return None");
300 PyGILState_Release(gstate);
303 throw sigrok::Error(SR_ERR);
309 /* Cast PacketPayload pointers to correct subclass type. */
310 %ignore sigrok::Packet::payload;
312 %extend sigrok::Packet
314 std::shared_ptr<sigrok::Header> _payload_header()
316 return dynamic_pointer_cast<sigrok::Header>($self->payload());
318 std::shared_ptr<sigrok::Meta> _payload_meta()
320 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
322 std::shared_ptr<sigrok::Analog> _payload_analog()
324 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
326 std::shared_ptr<sigrok::Logic> _payload_logic()
328 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
332 %extend sigrok::Packet
337 if self.type == PacketType.HEADER:
338 return self._payload_header()
339 elif self.type == PacketType.META:
340 return self._payload_meta()
341 elif self.type == PacketType.LOGIC:
342 return self._payload_logic()
343 elif self.type == PacketType.ANALOG:
344 return self._payload_analog()
348 payload = property(_payload)
354 #include "libsigrok/libsigrok.hpp"
356 /* Convert from a Python dict to a std::map<std::string, std::string> */
357 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
359 if (!PyDict_Check(dict))
360 throw sigrok::Error(SR_ERR_ARG);
362 std::map<std::string, std::string> output;
364 PyObject *py_key, *py_value;
367 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
368 if (!PyString_Check(py_key))
369 throw sigrok::Error(SR_ERR_ARG);
370 if (!PyString_Check(py_value))
371 throw sigrok::Error(SR_ERR_ARG);
372 auto key = PyString_AsString(py_key);
373 auto value = PyString_AsString(py_value);
380 /* Convert from a Python type to Glib::Variant, according to config key data type. */
381 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
383 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
385 if (type == SR_T_UINT64 && PyInt_Check(input))
386 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
387 if (type == SR_T_UINT64 && PyLong_Check(input))
388 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
389 else if (type == SR_T_STRING && PyString_Check(input))
390 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
391 else if (type == SR_T_BOOL && PyBool_Check(input))
392 return Glib::Variant<bool>::create(input == Py_True);
393 else if (type == SR_T_FLOAT && PyFloat_Check(input))
394 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
395 else if (type == SR_T_INT32 && PyInt_Check(input))
396 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
398 throw sigrok::Error(SR_ERR_ARG);
401 /* Convert from a Python type to Glib::Variant, according to Option data type. */
402 Glib::VariantBase python_to_variant_by_option(PyObject *input,
403 std::shared_ptr<sigrok::Option> option)
405 GVariantType *type = option->default_value().get_type().gobj();
407 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
408 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
409 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
410 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
411 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
412 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
413 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
414 return Glib::Variant<bool>::create(input == Py_True);
415 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
416 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
417 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
418 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
420 throw sigrok::Error(SR_ERR_ARG);
423 /* Convert from a Python dict to a std::map<std::string, std::string> */
424 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
425 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
427 if (!PyDict_Check(dict))
428 throw sigrok::Error(SR_ERR_ARG);
430 std::map<std::string, Glib::VariantBase> output;
432 PyObject *py_key, *py_value;
435 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
436 if (!PyString_Check(py_key))
437 throw sigrok::Error(SR_ERR_ARG);
438 auto key = PyString_AsString(py_key);
439 auto value = python_to_variant_by_option(py_value, options[key]);
448 /* Ignore these methods, we will override them below. */
449 %ignore sigrok::Driver::scan;
450 %ignore sigrok::InputFormat::create_input;
451 %ignore sigrok::OutputFormat::create_output;
455 %define %attributevector(Class, Type, Name, Get)
456 %rename(_ ## Get) sigrok::Class::Get;
457 %extend sigrok::Class
461 Name = property(_ ## Get)
466 %define %attributemap(Class, Type, Name, Get)
467 %rename(_ ## Get) sigrok::Class::Get;
468 %extend sigrok::Class
472 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
477 %define %enumextras(Class)
478 %extend sigrok::Class
487 def __eq__(self, other):
488 return (type(self) is type(other) and hash(self) == hash(other))
490 def __ne__(self, other):
491 return (type(self) is not type(other) or hash(self) != hash(other))
496 %include "../../../swig/classes.i"
498 /* Support Driver.scan() with keyword arguments. */
499 %extend sigrok::Driver
501 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
503 if (!PyDict_Check(dict))
504 throw sigrok::Error(SR_ERR_ARG);
506 PyObject *py_key, *py_value;
508 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
510 while (PyDict_Next(dict, &pos, &py_key, &py_value))
512 if (!PyString_Check(py_key))
513 throw sigrok::Error(SR_ERR_ARG);
514 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
515 auto value = python_to_variant_by_key(py_value, key);
516 options[key] = value;
519 return $self->scan(options);
525 def _Driver_scan(self, **kwargs):
526 return self._scan_kwargs(kwargs)
528 Driver.scan = _Driver_scan
531 /* Support InputFormat.create_input() with keyword arguments. */
532 %extend sigrok::InputFormat
534 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
536 return $self->create_input(
537 dict_to_map_options(dict, $self->options()));
543 def _InputFormat_create_input(self, **kwargs):
544 return self._create_input(kwargs)
546 InputFormat.create_input = _InputFormat_create_input
549 /* Support OutputFormat.create_output() with keyword arguments. */
550 %extend sigrok::OutputFormat
552 std::shared_ptr<sigrok::Output> _create_output_kwargs(
553 std::shared_ptr<sigrok::Device> device, PyObject *dict)
555 return $self->create_output(device,
556 dict_to_map_options(dict, $self->options()));
562 def _OutputFormat_create_output(self, device, **kwargs):
563 return self._create_output_kwargs(device, kwargs)
565 OutputFormat.create_output = _OutputFormat_create_output
568 /* Support config_set() with Python input types. */
569 %extend sigrok::Configurable
571 void config_set(const ConfigKey *key, PyObject *input)
573 $self->config_set(key, python_to_variant_by_key(input, key));