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
49 #include <pygobject.h>
50 #include <numpy/arrayobject.h>
52 PyObject *PyGObject_lib;
54 PyTypeObject *IOChannel;
59 #if PYGOBJECT_FLAGS_SIGNED
60 typedef gint pyg_flags_type;
62 typedef guint pyg_flags_type;
68 PyGObject_lib = pygobject_init(-1, -1, -1);
70 fprintf(stderr, "pygobject initialization failed.\n");
71 GLib = PyImport_ImportModule("gi.repository.GLib");
73 * This check can't save us if the import fails, but at least it gives us
74 * a starting point to trace the issue versus straight out crashing.
77 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
80 IOChannel = (PyTypeObject *) PyObject_GetAttrString(GLib, "IOChannel");
81 PollFD = (PyTypeObject *) PyObject_GetAttrString(GLib, "PollFD");
85 /* Map file objects to file descriptors. */
86 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
87 $1 = (PyObject_AsFileDescriptor($input) != -1);
91 int fd = PyObject_AsFileDescriptor($input);
93 SWIG_exception(SWIG_TypeError,
94 "Expected file object or integer file descriptor");
99 /* Map from Glib::Variant to native Python types. */
100 %typemap(out) Glib::VariantBase {
101 GValue *value = g_new0(GValue, 1);
102 g_value_init(value, G_TYPE_VARIANT);
103 g_value_set_variant(value, $1.gobj());
104 PyObject *variant = pyg_value_as_pyobject(value, true);
105 $result = PyObject_CallMethod(variant,
106 const_cast<char *>("unpack"),
107 const_cast<char *>(""), NULL);
112 /* Map from Glib::IOCondition to GLib.IOCondition. */
113 %typecheck(SWIG_TYPECHECK_POINTER) Glib::IOCondition {
114 pyg_flags_type flags;
115 $1 = pygobject_check($input, &PyGFlags_Type) &&
116 (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) != -1);
119 %typemap(in) Glib::IOCondition {
120 if (!pygobject_check($input, &PyGFlags_Type))
121 SWIG_exception(SWIG_TypeError, "Expected GLib.IOCondition value");
122 pyg_flags_type flags;
123 if (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) == -1)
124 SWIG_exception(SWIG_TypeError, "Not a valid Glib.IOCondition value");
125 $1 = (Glib::IOCondition) flags;
129 %typemap(out) Glib::IOCondition {
130 GValue *value = g_new0(GValue, 1);
131 g_value_init(value, G_TYPE_IO_CONDITION);
132 g_value_set_flags(value, &$1);
133 $result = pyg_value_as_pyobject(value, true);
137 /* Map from GLib.PollFD to Glib::PollFD *. */
138 %typecheck(SWIG_TYPECHECK_POINTER) Glib::PollFD {
139 $1 = pygobject_check($input, PollFD);
142 %typemap(in) Glib::PollFD {
143 if (!pygobject_check($input, PollFD))
144 SWIG_exception(SWIG_TypeError, "Expected GLib.PollFD");
145 PyObject *fd_obj = PyObject_GetAttrString($input, "fd");
146 PyObject *events_obj = PyObject_GetAttrString($input, "events");
147 pyg_flags_type flags;
148 pyg_flags_get_value(G_TYPE_IO_CONDITION, events_obj, &flags);
149 int fd = PyInt_AsLong(fd_obj);
150 Glib::IOCondition events = (Glib::IOCondition) flags;
151 $1 = Glib::PollFD(fd, events);
154 /* Map from GLib.IOChannel to Glib::IOChannel *. */
155 %typecheck(SWIG_TYPECHECK_POINTER) Glib::RefPtr<Glib::IOChannel> {
156 $1 = pygobject_check($input, IOChannel);
159 %typemap(in) Glib::RefPtr<Glib::IOChannel> {
160 if (!pygobject_check($input, IOChannel))
161 SWIG_exception(SWIG_TypeError, "Expected GLib.IOChannel");
162 $1 = Glib::wrap((GIOChannel *) PyObject_Hash($input), true);
165 /* Map from callable PyObject to SourceCallbackFunction. */
166 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SourceCallbackFunction {
167 $1 = PyCallable_Check($input);
170 %typemap(in) sigrok::SourceCallbackFunction {
171 if (!PyCallable_Check($input))
172 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
174 $1 = [=] (Glib::IOCondition revents) {
175 auto gstate = PyGILState_Ensure();
177 GValue *value = g_new0(GValue, 1);
178 g_value_init(value, G_TYPE_IO_CONDITION);
179 g_value_set_flags(value, revents);
180 auto revents_obj = pyg_value_as_pyobject(value, true);
183 auto arglist = Py_BuildValue("(O)", revents_obj);
185 auto result = PyEval_CallObject($input, arglist);
188 Py_XDECREF(revents_obj);
190 bool completed = !PyErr_Occurred();
195 bool valid_result = (completed && PyBool_Check(result));
197 if (completed && !valid_result)
199 PyErr_SetString(PyExc_TypeError,
200 "EventSource callback did not return a boolean");
204 bool retval = (valid_result && result == Py_True);
208 PyGILState_Release(gstate);
211 throw sigrok::Error(SR_ERR);
219 /* Map from callable PyObject to LogCallbackFunction */
220 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
221 $1 = PyCallable_Check($input);
224 %typemap(in) sigrok::LogCallbackFunction {
225 if (!PyCallable_Check($input))
226 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
228 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
229 auto gstate = PyGILState_Ensure();
231 auto log_obj = SWIG_NewPointerObj(
232 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
234 auto string_obj = PyString_FromString(message.c_str());
236 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
238 auto result = PyEval_CallObject($input, arglist);
242 Py_XDECREF(string_obj);
244 bool completed = !PyErr_Occurred();
249 bool valid_result = (completed && result == Py_None);
253 if (completed && !valid_result)
255 PyErr_SetString(PyExc_TypeError,
256 "Log callback did not return None");
260 PyGILState_Release(gstate);
263 throw sigrok::Error(SR_ERR);
269 /* Map from callable PyObject to DatafeedCallbackFunction */
270 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
271 $1 = PyCallable_Check($input);
274 %typemap(in) sigrok::DatafeedCallbackFunction {
275 if (!PyCallable_Check($input))
276 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
278 $1 = [=] (std::shared_ptr<sigrok::Device> device,
279 std::shared_ptr<sigrok::Packet> packet) {
280 auto gstate = PyGILState_Ensure();
282 auto device_obj = SWIG_NewPointerObj(
283 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
284 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
286 auto packet_obj = SWIG_NewPointerObj(
287 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
288 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
290 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
292 auto result = PyEval_CallObject($input, arglist);
295 Py_XDECREF(device_obj);
296 Py_XDECREF(packet_obj);
298 bool completed = !PyErr_Occurred();
303 bool valid_result = (completed && result == Py_None);
307 if (completed && !valid_result)
309 PyErr_SetString(PyExc_TypeError,
310 "Datafeed callback did not return None");
314 PyGILState_Release(gstate);
317 throw sigrok::Error(SR_ERR);
323 /* Cast PacketPayload pointers to correct subclass type. */
324 %ignore sigrok::Packet::payload;
326 %extend sigrok::Packet
328 std::shared_ptr<sigrok::Header> _payload_header()
330 return dynamic_pointer_cast<sigrok::Header>($self->payload());
332 std::shared_ptr<sigrok::Meta> _payload_meta()
334 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
336 std::shared_ptr<sigrok::Analog> _payload_analog()
338 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
340 std::shared_ptr<sigrok::Logic> _payload_logic()
342 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
346 %extend sigrok::Packet
351 if self.type == PacketType.HEADER:
352 return self._payload_header()
353 elif self.type == PacketType.META:
354 return self._payload_meta()
355 elif self.type == PacketType.LOGIC:
356 return self._payload_logic()
357 elif self.type == PacketType.ANALOG:
358 return self._payload_analog()
362 payload = property(_payload)
368 #include "libsigrokcxx/libsigrokcxx.hpp"
370 /* Convert from a Python dict to a std::map<std::string, std::string> */
371 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
373 if (!PyDict_Check(dict))
374 throw sigrok::Error(SR_ERR_ARG);
376 std::map<std::string, std::string> output;
378 PyObject *py_key, *py_value;
381 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
382 if (!PyString_Check(py_key))
383 throw sigrok::Error(SR_ERR_ARG);
384 if (!PyString_Check(py_value))
385 throw sigrok::Error(SR_ERR_ARG);
386 auto key = PyString_AsString(py_key);
387 auto value = PyString_AsString(py_value);
394 /* Convert from a Python type to Glib::Variant, according to config key data type. */
395 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
397 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
399 if (type == SR_T_UINT64 && PyInt_Check(input))
400 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
401 if (type == SR_T_UINT64 && PyLong_Check(input))
402 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
403 else if (type == SR_T_STRING && PyString_Check(input))
404 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
405 else if (type == SR_T_BOOL && PyBool_Check(input))
406 return Glib::Variant<bool>::create(input == Py_True);
407 else if (type == SR_T_FLOAT && PyFloat_Check(input))
408 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
409 else if (type == SR_T_INT32 && PyInt_Check(input))
410 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
412 throw sigrok::Error(SR_ERR_ARG);
415 /* Convert from a Python type to Glib::Variant, according to Option data type. */
416 Glib::VariantBase python_to_variant_by_option(PyObject *input,
417 std::shared_ptr<sigrok::Option> option)
419 GVariantType *type = option->default_value().get_type().gobj();
421 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
422 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
423 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
424 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
425 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
426 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
427 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
428 return Glib::Variant<bool>::create(input == Py_True);
429 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
430 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
431 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
432 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
434 throw sigrok::Error(SR_ERR_ARG);
437 /* Convert from a Python dict to a std::map<std::string, std::string> */
438 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
439 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
441 if (!PyDict_Check(dict))
442 throw sigrok::Error(SR_ERR_ARG);
444 std::map<std::string, Glib::VariantBase> output;
446 PyObject *py_key, *py_value;
449 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
450 if (!PyString_Check(py_key))
451 throw sigrok::Error(SR_ERR_ARG);
452 auto key = PyString_AsString(py_key);
453 auto value = python_to_variant_by_option(py_value, options[key]);
462 /* Ignore these methods, we will override them below. */
463 %ignore sigrok::Analog::data;
464 %ignore sigrok::Driver::scan;
465 %ignore sigrok::InputFormat::create_input;
466 %ignore sigrok::OutputFormat::create_output;
470 %define %attributevector(Class, Type, Name, Get)
471 %rename(_ ## Get) sigrok::Class::Get;
472 %extend sigrok::Class
476 Name = property(_ ## Get)
481 %define %attributemap(Class, Type, Name, Get)
482 %rename(_ ## Get) sigrok::Class::Get;
483 %extend sigrok::Class
487 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
492 %define %enumextras(Class)
493 %extend sigrok::Class
502 def __eq__(self, other):
503 return (type(self) is type(other) and hash(self) == hash(other))
505 def __ne__(self, other):
506 return (type(self) is not type(other) or hash(self) != hash(other))
511 %include "../../../swig/classes.i"
513 /* Support Driver.scan() with keyword arguments. */
514 %extend sigrok::Driver
516 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
518 if (!PyDict_Check(dict))
519 throw sigrok::Error(SR_ERR_ARG);
521 PyObject *py_key, *py_value;
523 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
525 while (PyDict_Next(dict, &pos, &py_key, &py_value))
527 if (!PyString_Check(py_key))
528 throw sigrok::Error(SR_ERR_ARG);
529 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
530 auto value = python_to_variant_by_key(py_value, key);
531 options[key] = value;
534 return $self->scan(options);
540 def _Driver_scan(self, **kwargs):
541 return self._scan_kwargs(kwargs)
543 Driver.scan = _Driver_scan
546 /* Support InputFormat.create_input() with keyword arguments. */
547 %extend sigrok::InputFormat
549 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
551 return $self->create_input(
552 dict_to_map_options(dict, $self->options()));
558 def _InputFormat_create_input(self, **kwargs):
559 return self._create_input(kwargs)
561 InputFormat.create_input = _InputFormat_create_input
564 /* Support OutputFormat.create_output() with keyword arguments. */
565 %extend sigrok::OutputFormat
567 std::shared_ptr<sigrok::Output> _create_output_kwargs(
568 std::shared_ptr<sigrok::Device> device, PyObject *dict)
570 return $self->create_output(device,
571 dict_to_map_options(dict, $self->options()));
577 def _OutputFormat_create_output(self, device, **kwargs):
578 return self._create_output_kwargs(device, kwargs)
580 OutputFormat.create_output = _OutputFormat_create_output
583 /* Support config_set() with Python input types. */
584 %extend sigrok::Configurable
586 void config_set(const ConfigKey *key, PyObject *input)
588 $self->config_set(key, python_to_variant_by_key(input, key));
592 /* Return NumPy array from Analog::data(). */
593 %extend sigrok::Analog
599 dims[0] = $self->channels().size();
600 dims[1] = $self->num_samples();
601 int typenum = NPY_FLOAT;
602 void *data = $self->data_pointer();
603 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
608 data = property(_data)