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);
311 #include "libsigrok/libsigrok.hpp"
313 /* Convert from a Python dict to a std::map<std::string, std::string> */
314 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
316 if (!PyDict_Check(dict))
317 throw sigrok::Error(SR_ERR_ARG);
319 std::map<std::string, std::string> output;
321 PyObject *py_key, *py_value;
324 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
325 if (!PyString_Check(py_key))
326 throw sigrok::Error(SR_ERR_ARG);
327 if (!PyString_Check(py_value))
328 throw sigrok::Error(SR_ERR_ARG);
329 auto key = PyString_AsString(py_key);
330 auto value = PyString_AsString(py_value);
337 /* Convert from a Python type to Glib::Variant, according to config key data type. */
338 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
340 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
342 if (type == SR_T_UINT64 && PyInt_Check(input))
343 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
344 if (type == SR_T_UINT64 && PyLong_Check(input))
345 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
346 else if (type == SR_T_STRING && PyString_Check(input))
347 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
348 else if (type == SR_T_BOOL && PyBool_Check(input))
349 return Glib::Variant<bool>::create(input == Py_True);
350 else if (type == SR_T_FLOAT && PyFloat_Check(input))
351 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
352 else if (type == SR_T_INT32 && PyInt_Check(input))
353 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
355 throw sigrok::Error(SR_ERR_ARG);
358 /* Convert from a Python type to Glib::Variant, according to Option data type. */
359 Glib::VariantBase python_to_variant_by_option(PyObject *input,
360 std::shared_ptr<sigrok::Option> option)
362 GVariantType *type = option->default_value().get_type().gobj();
364 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
365 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
366 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
367 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
368 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
369 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
370 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
371 return Glib::Variant<bool>::create(input == Py_True);
372 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
373 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
374 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
375 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
377 throw sigrok::Error(SR_ERR_ARG);
380 /* Convert from a Python dict to a std::map<std::string, std::string> */
381 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
382 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
384 if (!PyDict_Check(dict))
385 throw sigrok::Error(SR_ERR_ARG);
387 std::map<std::string, Glib::VariantBase> output;
389 PyObject *py_key, *py_value;
392 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
393 if (!PyString_Check(py_key))
394 throw sigrok::Error(SR_ERR_ARG);
395 auto key = PyString_AsString(py_key);
396 auto value = python_to_variant_by_option(py_value, options[key]);
405 /* Ignore these methods, we will override them below. */
406 %ignore sigrok::Driver::scan;
407 %ignore sigrok::InputFormat::create_input;
408 %ignore sigrok::OutputFormat::create_output;
412 %define %attributevector(Class, Type, Name, Get)
413 %rename(_ ## Get) sigrok::Class::Get;
414 %extend sigrok::Class
418 Name = property(_ ## Get)
423 %define %attributemap(Class, Type, Name, Get)
424 %rename(_ ## Get) sigrok::Class::Get;
425 %extend sigrok::Class
429 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
434 %define %enumextras(Class)
435 %extend sigrok::Class
444 def __eq__(self, other):
445 return (type(self) is type(other) and hash(self) == hash(other))
447 def __ne__(self, other):
448 return (type(self) is not type(other) or hash(self) != hash(other))
453 %include "../../../swig/classes.i"
455 /* Support Driver.scan() with keyword arguments. */
456 %extend sigrok::Driver
458 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
460 if (!PyDict_Check(dict))
461 throw sigrok::Error(SR_ERR_ARG);
463 PyObject *py_key, *py_value;
465 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
467 while (PyDict_Next(dict, &pos, &py_key, &py_value))
469 if (!PyString_Check(py_key))
470 throw sigrok::Error(SR_ERR_ARG);
471 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
472 auto value = python_to_variant_by_key(py_value, key);
473 options[key] = value;
476 return $self->scan(options);
482 def _Driver_scan(self, **kwargs):
483 return self._scan_kwargs(kwargs)
485 Driver.scan = _Driver_scan
488 /* Support InputFormat.create_input() with keyword arguments. */
489 %extend sigrok::InputFormat
491 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
493 return $self->create_input(
494 dict_to_map_options(dict, $self->options()));
500 def _InputFormat_create_input(self, **kwargs):
501 return self._create_input(kwargs)
503 InputFormat.create_input = _InputFormat_create_input
506 /* Support OutputFormat.create_output() with keyword arguments. */
507 %extend sigrok::OutputFormat
509 std::shared_ptr<sigrok::Output> _create_output_kwargs(
510 std::shared_ptr<sigrok::Device> device, PyObject *dict)
512 return $self->create_output(device,
513 dict_to_map_options(dict, $self->options()));
519 def _OutputFormat_create_output(self, device, **kwargs):
520 return self._create_output_kwargs(device, kwargs)
522 OutputFormat.create_output = _OutputFormat_create_output
525 /* Support config_set() with Python input types. */
526 %extend sigrok::Configurable
528 void config_set(const ConfigKey *key, PyObject *input)
530 $self->config_set(key, python_to_variant_by_key(input, key));