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 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
51 #include <numpy/arrayobject.h>
53 PyObject *PyGObject_lib;
58 #if PYGOBJECT_FLAGS_SIGNED
59 typedef gint pyg_flags_type;
61 typedef guint pyg_flags_type;
67 PyGObject_lib = pygobject_init(-1, -1, -1);
69 fprintf(stderr, "pygobject initialization failed.\n");
70 GLib = PyImport_ImportModule("gi.repository.GLib");
72 * This check can't save us if the import fails, but at least it gives us
73 * a starting point to trace the issue versus straight out crashing.
76 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
77 #if PY_VERSION_HEX >= 0x03000000
86 %include "../../../swig/templates.i"
88 /* Map file objects to file descriptors. */
89 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
90 $1 = (PyObject_AsFileDescriptor($input) != -1);
93 /* Map from Glib::Variant to native Python types. */
94 %typemap(out) Glib::VariantBase {
95 GValue *value = g_new0(GValue, 1);
96 g_value_init(value, G_TYPE_VARIANT);
97 g_value_set_variant(value, $1.gobj());
98 PyObject *variant = pyg_value_as_pyobject(value, true);
99 $result = PyObject_CallMethod(variant,
100 const_cast<char *>("unpack"), nullptr);
105 /* Map from callable PyObject to LogCallbackFunction */
106 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
107 $1 = PyCallable_Check($input);
110 %typemap(in) sigrok::LogCallbackFunction {
111 if (!PyCallable_Check($input))
112 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
114 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
115 auto gstate = PyGILState_Ensure();
117 auto log_obj = SWIG_NewPointerObj(
118 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
120 auto string_obj = PyString_FromString(message.c_str());
122 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
124 auto result = PyEval_CallObject($input, arglist);
128 Py_XDECREF(string_obj);
130 bool completed = !PyErr_Occurred();
135 bool valid_result = (completed && result == Py_None);
139 if (completed && !valid_result)
141 PyErr_SetString(PyExc_TypeError,
142 "Log callback did not return None");
146 PyGILState_Release(gstate);
149 throw sigrok::Error(SR_ERR);
155 /* Map from callable PyObject to SessionStoppedCallback */
156 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SessionStoppedCallback {
157 $1 = PyCallable_Check($input);
160 %typemap(in) sigrok::SessionStoppedCallback {
161 if (!PyCallable_Check($input))
162 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
165 const auto gstate = PyGILState_Ensure();
167 const auto result = PyEval_CallObject($input, nullptr);
168 const bool completed = !PyErr_Occurred();
169 const bool valid_result = (completed && result == Py_None);
171 if (completed && !valid_result) {
172 PyErr_SetString(PyExc_TypeError,
173 "Session stop callback did not return None");
179 PyGILState_Release(gstate);
182 throw sigrok::Error(SR_ERR);
188 /* Map from callable PyObject to DatafeedCallbackFunction */
189 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
190 $1 = PyCallable_Check($input);
193 %typemap(in) sigrok::DatafeedCallbackFunction {
194 if (!PyCallable_Check($input))
195 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
197 $1 = [=] (std::shared_ptr<sigrok::Device> device,
198 std::shared_ptr<sigrok::Packet> packet) {
199 auto gstate = PyGILState_Ensure();
201 auto device_obj = SWIG_NewPointerObj(
202 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
203 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
205 auto packet_obj = SWIG_NewPointerObj(
206 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
207 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
209 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
211 auto result = PyEval_CallObject($input, arglist);
214 Py_XDECREF(device_obj);
215 Py_XDECREF(packet_obj);
217 bool completed = !PyErr_Occurred();
222 bool valid_result = (completed && result == Py_None);
226 if (completed && !valid_result)
228 PyErr_SetString(PyExc_TypeError,
229 "Datafeed callback did not return None");
233 PyGILState_Release(gstate);
236 throw sigrok::Error(SR_ERR);
242 /* Cast PacketPayload pointers to correct subclass type. */
243 %ignore sigrok::Packet::payload;
245 %extend sigrok::Packet
247 std::shared_ptr<sigrok::Header> _payload_header()
249 return dynamic_pointer_cast<sigrok::Header>($self->payload());
251 std::shared_ptr<sigrok::Meta> _payload_meta()
253 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
255 std::shared_ptr<sigrok::Analog> _payload_analog()
257 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
259 std::shared_ptr<sigrok::Logic> _payload_logic()
261 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
265 %extend sigrok::Packet
270 if self.type == PacketType.HEADER:
271 return self._payload_header()
272 elif self.type == PacketType.META:
273 return self._payload_meta()
274 elif self.type == PacketType.LOGIC:
275 return self._payload_logic()
276 elif self.type == PacketType.ANALOG:
277 return self._payload_analog()
281 payload = property(_payload)
287 #include "libsigrokcxx/libsigrokcxx.hpp"
289 /* Convert from a Python dict to a std::map<std::string, std::string> */
290 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
292 if (!PyDict_Check(dict))
293 throw sigrok::Error(SR_ERR_ARG);
295 std::map<std::string, std::string> output;
297 PyObject *py_key, *py_value;
300 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
301 if (!PyString_Check(py_key))
302 throw sigrok::Error(SR_ERR_ARG);
303 if (!PyString_Check(py_value))
304 throw sigrok::Error(SR_ERR_ARG);
305 auto key = PyString_AsString(py_key);
306 auto value = PyString_AsString(py_value);
313 /* Convert from a Python type to Glib::Variant, according to config key data type. */
314 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
316 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
318 if (type == SR_T_UINT64 && PyInt_Check(input))
319 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
320 if (type == SR_T_UINT64 && PyLong_Check(input))
321 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
322 else if (type == SR_T_STRING && PyString_Check(input))
323 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
324 else if (type == SR_T_BOOL && PyBool_Check(input))
325 return Glib::Variant<bool>::create(input == Py_True);
326 else if (type == SR_T_FLOAT && PyFloat_Check(input))
327 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
328 else if (type == SR_T_INT32 && PyInt_Check(input))
329 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
331 throw sigrok::Error(SR_ERR_ARG);
334 /* Convert from a Python type to Glib::Variant, according to Option data type. */
335 Glib::VariantBase python_to_variant_by_option(PyObject *input,
336 std::shared_ptr<sigrok::Option> option)
338 GVariantType *type = option->default_value().get_type().gobj();
340 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
341 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
342 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
343 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
344 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
345 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
346 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
347 return Glib::Variant<bool>::create(input == Py_True);
348 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
349 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
350 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
351 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
353 throw sigrok::Error(SR_ERR_ARG);
356 /* Convert from a Python dict to a std::map<std::string, std::string> */
357 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
358 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
360 if (!PyDict_Check(dict))
361 throw sigrok::Error(SR_ERR_ARG);
363 std::map<std::string, Glib::VariantBase> output;
365 PyObject *py_key, *py_value;
368 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
369 if (!PyString_Check(py_key))
370 throw sigrok::Error(SR_ERR_ARG);
371 auto key = PyString_AsString(py_key);
372 auto value = python_to_variant_by_option(py_value, options[key]);
381 /* Ignore these methods, we will override them below. */
382 %ignore sigrok::Analog::data;
383 %ignore sigrok::Driver::scan;
384 %ignore sigrok::InputFormat::create_input;
385 %ignore sigrok::OutputFormat::create_output;
387 %include "doc_start.i"
389 %define %attributevector(Class, Type, Name, Get)
390 %rename(_ ## Get) sigrok::Class::Get;
391 %extend sigrok::Class
395 Name = property(_ ## Get)
400 %define %attributemap(Class, Type, Name, Get)
401 %rename(_ ## Get) sigrok::Class::Get;
402 %extend sigrok::Class
406 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
411 %define %enumextras(Class)
412 %extend sigrok::Class
421 def __eq__(self, other):
422 return (type(self) is type(other) and hash(self) == hash(other))
424 def __ne__(self, other):
425 return (type(self) is not type(other) or hash(self) != hash(other))
430 %include "../../../swig/classes.i"
432 /* Support Driver.scan() with keyword arguments. */
433 %extend sigrok::Driver
435 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
437 if (!PyDict_Check(dict))
438 throw sigrok::Error(SR_ERR_ARG);
440 PyObject *py_key, *py_value;
442 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
444 while (PyDict_Next(dict, &pos, &py_key, &py_value))
446 if (!PyString_Check(py_key))
447 throw sigrok::Error(SR_ERR_ARG);
448 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
449 auto value = python_to_variant_by_key(py_value, key);
450 options[key] = value;
453 return $self->scan(options);
459 def _Driver_scan(self, **kwargs):
460 return self._scan_kwargs(kwargs)
462 Driver.scan = _Driver_scan
465 /* Support InputFormat.create_input() with keyword arguments. */
466 %extend sigrok::InputFormat
468 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
470 return $self->create_input(
471 dict_to_map_options(dict, $self->options()));
477 def _InputFormat_create_input(self, **kwargs):
478 return self._create_input(kwargs)
480 InputFormat.create_input = _InputFormat_create_input
483 /* Support OutputFormat.create_output() with keyword arguments. */
484 %extend sigrok::OutputFormat
486 std::shared_ptr<sigrok::Output> _create_output_kwargs(
487 std::shared_ptr<sigrok::Device> device, PyObject *dict)
489 return $self->create_output(device,
490 dict_to_map_options(dict, $self->options()));
496 def _OutputFormat_create_output(self, device, **kwargs):
497 return self._create_output_kwargs(device, kwargs)
499 OutputFormat.create_output = _OutputFormat_create_output
502 /* Support config_set() with Python input types. */
503 %extend sigrok::Configurable
505 void config_set(const ConfigKey *key, PyObject *input)
507 $self->config_set(key, python_to_variant_by_key(input, key));
511 /* Return NumPy array from Analog::data(). */
512 %extend sigrok::Analog
518 dims[0] = $self->channels().size();
519 dims[1] = $self->num_samples();
520 int typenum = NPY_FLOAT;
521 void *data = $self->data_pointer();
522 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
527 data = property(_data)