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;
57 #if PYGOBJECT_FLAGS_SIGNED
58 typedef gint pyg_flags_type;
60 typedef guint pyg_flags_type;
66 PyGObject_lib = pygobject_init(-1, -1, -1);
68 fprintf(stderr, "pygobject initialization failed.\n");
69 GLib = PyImport_ImportModule("gi.repository.GLib");
71 * This check can't save us if the import fails, but at least it gives us
72 * a starting point to trace the issue versus straight out crashing.
75 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
76 #if PY_VERSION_HEX >= 0x03000000
85 /* Map file objects to file descriptors. */
86 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
87 $1 = (PyObject_AsFileDescriptor($input) != -1);
90 /* Map from Glib::Variant to native Python types. */
91 %typemap(out) Glib::VariantBase {
92 GValue *value = g_new0(GValue, 1);
93 g_value_init(value, G_TYPE_VARIANT);
94 g_value_set_variant(value, $1.gobj());
95 PyObject *variant = pyg_value_as_pyobject(value, true);
96 $result = PyObject_CallMethod(variant,
97 const_cast<char *>("unpack"), nullptr);
102 /* Map from callable PyObject to LogCallbackFunction */
103 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
104 $1 = PyCallable_Check($input);
107 %typemap(in) sigrok::LogCallbackFunction {
108 if (!PyCallable_Check($input))
109 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
111 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
112 auto gstate = PyGILState_Ensure();
114 auto log_obj = SWIG_NewPointerObj(
115 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
117 auto string_obj = PyString_FromString(message.c_str());
119 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
121 auto result = PyEval_CallObject($input, arglist);
125 Py_XDECREF(string_obj);
127 bool completed = !PyErr_Occurred();
132 bool valid_result = (completed && result == Py_None);
136 if (completed && !valid_result)
138 PyErr_SetString(PyExc_TypeError,
139 "Log callback did not return None");
143 PyGILState_Release(gstate);
146 throw sigrok::Error(SR_ERR);
152 /* Map from callable PyObject to SessionStoppedCallback */
153 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SessionStoppedCallback {
154 $1 = PyCallable_Check($input);
157 %typemap(in) sigrok::SessionStoppedCallback {
158 if (!PyCallable_Check($input))
159 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
162 const auto gstate = PyGILState_Ensure();
164 const auto result = PyEval_CallObject($input, nullptr);
165 const bool completed = !PyErr_Occurred();
166 const bool valid_result = (completed && result == Py_None);
168 if (completed && !valid_result) {
169 PyErr_SetString(PyExc_TypeError,
170 "Session stop callback did not return None");
176 PyGILState_Release(gstate);
179 throw sigrok::Error(SR_ERR);
185 /* Map from callable PyObject to DatafeedCallbackFunction */
186 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
187 $1 = PyCallable_Check($input);
190 %typemap(in) sigrok::DatafeedCallbackFunction {
191 if (!PyCallable_Check($input))
192 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
194 $1 = [=] (std::shared_ptr<sigrok::Device> device,
195 std::shared_ptr<sigrok::Packet> packet) {
196 auto gstate = PyGILState_Ensure();
198 auto device_obj = SWIG_NewPointerObj(
199 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
200 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
202 auto packet_obj = SWIG_NewPointerObj(
203 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
204 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
206 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
208 auto result = PyEval_CallObject($input, arglist);
211 Py_XDECREF(device_obj);
212 Py_XDECREF(packet_obj);
214 bool completed = !PyErr_Occurred();
219 bool valid_result = (completed && result == Py_None);
223 if (completed && !valid_result)
225 PyErr_SetString(PyExc_TypeError,
226 "Datafeed callback did not return None");
230 PyGILState_Release(gstate);
233 throw sigrok::Error(SR_ERR);
239 /* Cast PacketPayload pointers to correct subclass type. */
240 %ignore sigrok::Packet::payload;
242 %extend sigrok::Packet
244 std::shared_ptr<sigrok::Header> _payload_header()
246 return dynamic_pointer_cast<sigrok::Header>($self->payload());
248 std::shared_ptr<sigrok::Meta> _payload_meta()
250 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
252 std::shared_ptr<sigrok::Analog> _payload_analog()
254 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
256 std::shared_ptr<sigrok::Logic> _payload_logic()
258 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
262 %extend sigrok::Packet
267 if self.type == PacketType.HEADER:
268 return self._payload_header()
269 elif self.type == PacketType.META:
270 return self._payload_meta()
271 elif self.type == PacketType.LOGIC:
272 return self._payload_logic()
273 elif self.type == PacketType.ANALOG:
274 return self._payload_analog()
278 payload = property(_payload)
284 #include "libsigrokcxx/libsigrokcxx.hpp"
286 /* Convert from a Python dict to a std::map<std::string, std::string> */
287 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
289 if (!PyDict_Check(dict))
290 throw sigrok::Error(SR_ERR_ARG);
292 std::map<std::string, std::string> output;
294 PyObject *py_key, *py_value;
297 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
298 if (!PyString_Check(py_key))
299 throw sigrok::Error(SR_ERR_ARG);
300 if (!PyString_Check(py_value))
301 throw sigrok::Error(SR_ERR_ARG);
302 auto key = PyString_AsString(py_key);
303 auto value = PyString_AsString(py_value);
310 /* Convert from a Python type to Glib::Variant, according to config key data type. */
311 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
313 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
315 if (type == SR_T_UINT64 && PyInt_Check(input))
316 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
317 if (type == SR_T_UINT64 && PyLong_Check(input))
318 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
319 else if (type == SR_T_STRING && PyString_Check(input))
320 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
321 else if (type == SR_T_BOOL && PyBool_Check(input))
322 return Glib::Variant<bool>::create(input == Py_True);
323 else if (type == SR_T_FLOAT && PyFloat_Check(input))
324 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
325 else if (type == SR_T_INT32 && PyInt_Check(input))
326 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
328 throw sigrok::Error(SR_ERR_ARG);
331 /* Convert from a Python type to Glib::Variant, according to Option data type. */
332 Glib::VariantBase python_to_variant_by_option(PyObject *input,
333 std::shared_ptr<sigrok::Option> option)
335 GVariantType *type = option->default_value().get_type().gobj();
337 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
338 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
339 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
340 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
341 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
342 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
343 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
344 return Glib::Variant<bool>::create(input == Py_True);
345 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
346 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
347 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
348 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
350 throw sigrok::Error(SR_ERR_ARG);
353 /* Convert from a Python dict to a std::map<std::string, std::string> */
354 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
355 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
357 if (!PyDict_Check(dict))
358 throw sigrok::Error(SR_ERR_ARG);
360 std::map<std::string, Glib::VariantBase> output;
362 PyObject *py_key, *py_value;
365 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
366 if (!PyString_Check(py_key))
367 throw sigrok::Error(SR_ERR_ARG);
368 auto key = PyString_AsString(py_key);
369 auto value = python_to_variant_by_option(py_value, options[key]);
378 /* Ignore these methods, we will override them below. */
379 %ignore sigrok::Analog::data;
380 %ignore sigrok::Driver::scan;
381 %ignore sigrok::InputFormat::create_input;
382 %ignore sigrok::OutputFormat::create_output;
386 %define %attributevector(Class, Type, Name, Get)
387 %rename(_ ## Get) sigrok::Class::Get;
388 %extend sigrok::Class
392 Name = property(_ ## Get)
397 %define %attributemap(Class, Type, Name, Get)
398 %rename(_ ## Get) sigrok::Class::Get;
399 %extend sigrok::Class
403 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
408 %define %enumextras(Class)
409 %extend sigrok::Class
418 def __eq__(self, other):
419 return (type(self) is type(other) and hash(self) == hash(other))
421 def __ne__(self, other):
422 return (type(self) is not type(other) or hash(self) != hash(other))
427 %include "../../../swig/classes.i"
429 /* Support Driver.scan() with keyword arguments. */
430 %extend sigrok::Driver
432 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
434 if (!PyDict_Check(dict))
435 throw sigrok::Error(SR_ERR_ARG);
437 PyObject *py_key, *py_value;
439 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
441 while (PyDict_Next(dict, &pos, &py_key, &py_value))
443 if (!PyString_Check(py_key))
444 throw sigrok::Error(SR_ERR_ARG);
445 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
446 auto value = python_to_variant_by_key(py_value, key);
447 options[key] = value;
450 return $self->scan(options);
456 def _Driver_scan(self, **kwargs):
457 return self._scan_kwargs(kwargs)
459 Driver.scan = _Driver_scan
462 /* Support InputFormat.create_input() with keyword arguments. */
463 %extend sigrok::InputFormat
465 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
467 return $self->create_input(
468 dict_to_map_options(dict, $self->options()));
474 def _InputFormat_create_input(self, **kwargs):
475 return self._create_input(kwargs)
477 InputFormat.create_input = _InputFormat_create_input
480 /* Support OutputFormat.create_output() with keyword arguments. */
481 %extend sigrok::OutputFormat
483 std::shared_ptr<sigrok::Output> _create_output_kwargs(
484 std::shared_ptr<sigrok::Device> device, PyObject *dict)
486 return $self->create_output(device,
487 dict_to_map_options(dict, $self->options()));
493 def _OutputFormat_create_output(self, device, **kwargs):
494 return self._create_output_kwargs(device, kwargs)
496 OutputFormat.create_output = _OutputFormat_create_output
499 /* Support config_set() with Python input types. */
500 %extend sigrok::Configurable
502 void config_set(const ConfigKey *key, PyObject *input)
504 $self->config_set(key, python_to_variant_by_key(input, key));
508 /* Return NumPy array from Analog::data(). */
509 %extend sigrok::Analog
515 dims[0] = $self->channels().size();
516 dims[1] = $self->num_samples();
517 int typenum = NPY_FLOAT;
518 void *data = $self->data_pointer();
519 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
524 data = property(_data)