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
51 #include <pygobject.h>
52 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
53 #include <numpy/arrayobject.h>
55 PyObject *PyGObject_lib;
58 #if PYGOBJECT_FLAGS_SIGNED
59 typedef gint pyg_flags_type;
61 typedef guint pyg_flags_type;
64 #if PY_VERSION_HEX >= 0x03000000
65 #define string_check PyUnicode_Check
66 #define string_from_python PyUnicode_AsUTF8
67 #define string_to_python PyUnicode_FromString
69 #define string_check PyString_Check
70 #define string_from_python PyString_AsString
71 #define string_to_python PyString_FromString
77 PyGObject_lib = pygobject_init(-1, -1, -1);
79 fprintf(stderr, "pygobject initialization failed.\n");
80 GLib = PyImport_ImportModule("gi.repository.GLib");
82 * This check can't save us if the import fails, but at least it gives us
83 * a starting point to trace the issue versus straight out crashing.
86 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
87 #if PY_VERSION_HEX >= 0x03000000
96 %include "../../../swig/templates.i"
98 /* Map file objects to file descriptors. */
99 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
100 $1 = (PyObject_AsFileDescriptor($input) != -1);
103 /* Map from Glib::Variant to native Python types. */
104 %typemap(out) Glib::VariantBase {
105 GValue *value = g_new0(GValue, 1);
106 g_value_init(value, G_TYPE_VARIANT);
107 g_value_set_variant(value, $1.gobj());
108 PyObject *variant = pyg_value_as_pyobject(value, true);
109 $result = PyObject_CallMethod(variant,
110 const_cast<char *>("unpack"), nullptr);
115 /* Use the same typemap above for Glib::VariantContainerBase */
116 %apply Glib::VariantBase { Glib::VariantContainerBase }
118 /* Map from callable PyObject to LogCallbackFunction */
119 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
120 $1 = PyCallable_Check($input);
123 %typemap(in) sigrok::LogCallbackFunction {
124 if (!PyCallable_Check($input))
125 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
127 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
128 auto gstate = PyGILState_Ensure();
130 auto log_obj = SWIG_NewPointerObj(
131 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
133 auto string_obj = string_to_python(message.c_str());
135 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
137 auto result = PyObject_CallObject($input, arglist);
141 Py_XDECREF(string_obj);
143 bool completed = !PyErr_Occurred();
148 bool valid_result = (completed && result == Py_None);
152 if (completed && !valid_result)
154 PyErr_SetString(PyExc_TypeError,
155 "Log callback did not return None");
159 PyGILState_Release(gstate);
162 throw sigrok::Error(SR_ERR);
168 /* Map from callable PyObject to SessionStoppedCallback */
169 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SessionStoppedCallback {
170 $1 = PyCallable_Check($input);
173 %typemap(in) sigrok::SessionStoppedCallback {
174 if (!PyCallable_Check($input))
175 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
178 const auto gstate = PyGILState_Ensure();
180 const auto result = PyObject_CallObject($input, nullptr);
181 const bool completed = !PyErr_Occurred();
182 const bool valid_result = (completed && result == Py_None);
184 if (completed && !valid_result) {
185 PyErr_SetString(PyExc_TypeError,
186 "Session stop callback did not return None");
192 PyGILState_Release(gstate);
195 throw sigrok::Error(SR_ERR);
201 /* Map from callable PyObject to DatafeedCallbackFunction */
202 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
203 $1 = PyCallable_Check($input);
206 %typemap(in) sigrok::DatafeedCallbackFunction {
207 if (!PyCallable_Check($input))
208 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
210 $1 = [=] (std::shared_ptr<sigrok::Device> device,
211 std::shared_ptr<sigrok::Packet> packet) {
212 auto gstate = PyGILState_Ensure();
214 auto device_obj = SWIG_NewPointerObj(
215 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
216 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
218 auto packet_obj = SWIG_NewPointerObj(
219 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
220 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
222 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
224 auto result = PyObject_CallObject($input, arglist);
227 Py_XDECREF(device_obj);
228 Py_XDECREF(packet_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 "Datafeed callback did not return None");
246 PyGILState_Release(gstate);
249 throw sigrok::Error(SR_ERR);
255 /* Cast PacketPayload pointers to correct subclass type. */
256 %ignore sigrok::Packet::payload;
258 %extend sigrok::Packet
260 std::shared_ptr<sigrok::Header> _payload_header()
262 return dynamic_pointer_cast<sigrok::Header>($self->payload());
264 std::shared_ptr<sigrok::Meta> _payload_meta()
266 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
268 std::shared_ptr<sigrok::Analog> _payload_analog()
270 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
272 std::shared_ptr<sigrok::Logic> _payload_logic()
274 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
278 %extend sigrok::Packet
283 if self.type == PacketType.HEADER:
284 return self._payload_header()
285 elif self.type == PacketType.META:
286 return self._payload_meta()
287 elif self.type == PacketType.LOGIC:
288 return self._payload_logic()
289 elif self.type == PacketType.ANALOG:
290 return self._payload_analog()
294 payload = property(_payload)
300 #include "libsigrokcxx/libsigrokcxx.hpp"
302 /* Convert from a Python dict to a std::map<std::string, std::string> */
303 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
305 if (!PyDict_Check(dict))
306 throw sigrok::Error(SR_ERR_ARG);
308 std::map<std::string, std::string> output;
310 PyObject *py_key, *py_value;
313 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
314 if (!string_check(py_key))
315 throw sigrok::Error(SR_ERR_ARG);
316 if (!string_check(py_value))
317 throw sigrok::Error(SR_ERR_ARG);
318 auto key = string_from_python(py_key);
319 auto value = string_from_python(py_value);
326 /* Convert from a Python type to Glib::Variant, according to config key data type. */
327 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
329 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
331 if (type == SR_T_UINT64 && PyInt_Check(input))
332 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
333 if (type == SR_T_UINT64 && PyLong_Check(input))
334 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
335 else if (type == SR_T_STRING && string_check(input))
336 return Glib::Variant<Glib::ustring>::create(string_from_python(input));
337 else if (type == SR_T_BOOL && PyBool_Check(input))
338 return Glib::Variant<bool>::create(input == Py_True);
339 else if (type == SR_T_FLOAT && PyFloat_Check(input))
340 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
341 else if (type == SR_T_INT32 && PyInt_Check(input))
342 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
343 else if (type == SR_T_UINT32 && PyInt_Check(input))
344 return Glib::Variant<guint32>::create(PyInt_AsLong(input));
345 else if ((type == SR_T_RATIONAL_VOLT) && PyTuple_Check(input) && (PyTuple_Size(input) == 2)) {
346 PyObject *numObj = PyTuple_GetItem(input, 0);
347 PyObject *denomObj = PyTuple_GetItem(input, 1);
348 if ((PyInt_Check(numObj) || PyLong_Check(numObj)) && (PyInt_Check(denomObj) || PyLong_Check(denomObj))) {
349 const std::vector<guint64> v = {(guint64)PyInt_AsLong(numObj), (guint64)PyInt_AsLong(denomObj)};
350 return Glib::Variant< std::vector<guint64> >::create(v);
353 throw sigrok::Error(SR_ERR_ARG);
356 /* Convert from a Python type to Glib::Variant, according to Option data type. */
357 Glib::VariantBase python_to_variant_by_option(PyObject *input,
358 std::shared_ptr<sigrok::Option> option)
360 GVariantType *type = option->default_value().get_type().gobj();
362 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
363 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
364 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
365 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
366 else if (type == G_VARIANT_TYPE_STRING && string_check(input))
367 return Glib::Variant<Glib::ustring>::create(string_from_python(input));
368 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
369 return Glib::Variant<bool>::create(input == Py_True);
370 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
371 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
372 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
373 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
374 else if (type == G_VARIANT_TYPE_UINT32 && PyInt_Check(input))
375 return Glib::Variant<guint32>::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 (!string_check(py_key))
394 throw sigrok::Error(SR_ERR_ARG);
395 auto key = string_from_python(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::Analog::data;
407 %ignore sigrok::Logic::data;
408 %ignore sigrok::Driver::scan;
409 %ignore sigrok::InputFormat::create_input;
410 %ignore sigrok::OutputFormat::create_output;
412 %include "doc_start.i"
414 %define %attributevector(Class, Type, Name, Get)
415 %rename(_ ## Get) sigrok::Class::Get;
416 %extend sigrok::Class
420 Name = property(_ ## Get)
425 %define %attributemap(Class, Type, Name, Get)
426 %rename(_ ## Get) sigrok::Class::Get;
427 %extend sigrok::Class
431 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
436 %define %enumextras(Class)
437 %extend sigrok::Class
444 std::string __str__()
446 return $self->name();
449 std::string __repr__()
451 return "Class." + $self->name();
456 def __eq__(self, other):
457 return (type(self) is type(other) and hash(self) == hash(other))
459 def __ne__(self, other):
460 return (type(self) is not type(other) or hash(self) != hash(other))
465 %include "../../../swig/classes.i"
467 /* Support Driver.scan() with keyword arguments. */
468 %extend sigrok::Driver
470 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
472 if (!PyDict_Check(dict))
473 throw sigrok::Error(SR_ERR_ARG);
475 PyObject *py_key, *py_value;
477 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
479 while (PyDict_Next(dict, &pos, &py_key, &py_value))
481 if (!string_check(py_key))
482 throw sigrok::Error(SR_ERR_ARG);
483 auto key = sigrok::ConfigKey::get_by_identifier(string_from_python(py_key));
484 auto value = python_to_variant_by_key(py_value, key);
485 options[key] = value;
488 return $self->scan(options);
494 def _Driver_scan(self, **kwargs):
495 return self._scan_kwargs(kwargs)
497 Driver.scan = _Driver_scan
500 /* Support InputFormat.create_input() with keyword arguments. */
501 %extend sigrok::InputFormat
503 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
505 return $self->create_input(
506 dict_to_map_options(dict, $self->options()));
512 def _InputFormat_create_input(self, **kwargs):
513 return self._create_input(kwargs)
515 InputFormat.create_input = _InputFormat_create_input
518 /* Support OutputFormat.create_output() with keyword arguments. */
519 %extend sigrok::OutputFormat
521 std::shared_ptr<sigrok::Output> _create_output_kwargs(
522 std::shared_ptr<sigrok::Device> device, PyObject *dict)
524 return $self->create_output(device,
525 dict_to_map_options(dict, $self->options()));
531 def _OutputFormat_create_output(self, device, **kwargs):
532 return self._create_output_kwargs(device, kwargs)
534 OutputFormat.create_output = _OutputFormat_create_output
537 /* Support config_set() with Python input types. */
538 %extend sigrok::Configurable
540 void config_set(const ConfigKey *key, PyObject *input)
542 $self->config_set(key, python_to_variant_by_key(input, key));
546 /* Return NumPy array from Analog::data(). */
547 %extend sigrok::Analog
553 dims[0] = $self->channels().size();
554 dims[1] = $self->num_samples();
555 int typenum = NPY_FLOAT;
556 void *data = $self->data_pointer();
557 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
562 data = property(_data)
566 /* Return NumPy array from Logic::data(). */
567 %extend sigrok::Logic
572 dims[0] = $self->data_length() / $self->unit_size();
573 dims[1] = $self->unit_size();
574 int typenum = NPY_UINT8;
575 void *data = $self->data_pointer();
576 return PyArray_SimpleNewFromData(2, dims, typenum, data);
581 data = property(_data)
585 /* Create logic packet from Python buffer. */
586 %extend sigrok::Context
588 std::shared_ptr<Packet> _create_logic_packet_buf(PyObject *buf, unsigned int unit_size)
591 PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE);
592 return $self->create_logic_packet(view.buf, view.len, unit_size);
598 def _Context_create_logic_packet(self, buf, unit_size):
599 return self._create_logic_packet_buf(buf, unit_size)
601 Context.create_logic_packet = _Context_create_logic_packet