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"),
98 const_cast<char *>(""), NULL);
103 /* Map from callable PyObject to LogCallbackFunction */
104 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
105 $1 = PyCallable_Check($input);
108 %typemap(in) sigrok::LogCallbackFunction {
109 if (!PyCallable_Check($input))
110 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
112 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
113 auto gstate = PyGILState_Ensure();
115 auto log_obj = SWIG_NewPointerObj(
116 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
118 auto string_obj = PyString_FromString(message.c_str());
120 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
122 auto result = PyEval_CallObject($input, arglist);
126 Py_XDECREF(string_obj);
128 bool completed = !PyErr_Occurred();
133 bool valid_result = (completed && result == Py_None);
137 if (completed && !valid_result)
139 PyErr_SetString(PyExc_TypeError,
140 "Log callback did not return None");
144 PyGILState_Release(gstate);
147 throw sigrok::Error(SR_ERR);
153 /* Map from callable PyObject to SessionStoppedCallback */
154 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SessionStoppedCallback {
155 $1 = PyCallable_Check($input);
158 %typemap(in) sigrok::SessionStoppedCallback {
159 if (!PyCallable_Check($input))
160 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
163 const auto gstate = PyGILState_Ensure();
165 const auto result = PyEval_CallObject($input, nullptr);
166 const bool completed = !PyErr_Occurred();
167 const bool valid_result = (completed && result == Py_None);
169 if (completed && !valid_result) {
170 PyErr_SetString(PyExc_TypeError,
171 "Session stop callback did not return None");
177 PyGILState_Release(gstate);
180 throw sigrok::Error(SR_ERR);
186 /* Map from callable PyObject to DatafeedCallbackFunction */
187 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
188 $1 = PyCallable_Check($input);
191 %typemap(in) sigrok::DatafeedCallbackFunction {
192 if (!PyCallable_Check($input))
193 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
195 $1 = [=] (std::shared_ptr<sigrok::Device> device,
196 std::shared_ptr<sigrok::Packet> packet) {
197 auto gstate = PyGILState_Ensure();
199 auto device_obj = SWIG_NewPointerObj(
200 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
201 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
203 auto packet_obj = SWIG_NewPointerObj(
204 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
205 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
207 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
209 auto result = PyEval_CallObject($input, arglist);
212 Py_XDECREF(device_obj);
213 Py_XDECREF(packet_obj);
215 bool completed = !PyErr_Occurred();
220 bool valid_result = (completed && result == Py_None);
224 if (completed && !valid_result)
226 PyErr_SetString(PyExc_TypeError,
227 "Datafeed callback did not return None");
231 PyGILState_Release(gstate);
234 throw sigrok::Error(SR_ERR);
240 /* Cast PacketPayload pointers to correct subclass type. */
241 %ignore sigrok::Packet::payload;
243 %extend sigrok::Packet
245 std::shared_ptr<sigrok::Header> _payload_header()
247 return dynamic_pointer_cast<sigrok::Header>($self->payload());
249 std::shared_ptr<sigrok::Meta> _payload_meta()
251 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
253 std::shared_ptr<sigrok::Analog> _payload_analog()
255 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
257 std::shared_ptr<sigrok::Logic> _payload_logic()
259 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
263 %extend sigrok::Packet
268 if self.type == PacketType.HEADER:
269 return self._payload_header()
270 elif self.type == PacketType.META:
271 return self._payload_meta()
272 elif self.type == PacketType.LOGIC:
273 return self._payload_logic()
274 elif self.type == PacketType.ANALOG:
275 return self._payload_analog()
279 payload = property(_payload)
285 #include "libsigrokcxx/libsigrokcxx.hpp"
287 /* Convert from a Python dict to a std::map<std::string, std::string> */
288 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
290 if (!PyDict_Check(dict))
291 throw sigrok::Error(SR_ERR_ARG);
293 std::map<std::string, std::string> output;
295 PyObject *py_key, *py_value;
298 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
299 if (!PyString_Check(py_key))
300 throw sigrok::Error(SR_ERR_ARG);
301 if (!PyString_Check(py_value))
302 throw sigrok::Error(SR_ERR_ARG);
303 auto key = PyString_AsString(py_key);
304 auto value = PyString_AsString(py_value);
311 /* Convert from a Python type to Glib::Variant, according to config key data type. */
312 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
314 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
316 if (type == SR_T_UINT64 && PyInt_Check(input))
317 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
318 if (type == SR_T_UINT64 && PyLong_Check(input))
319 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
320 else if (type == SR_T_STRING && PyString_Check(input))
321 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
322 else if (type == SR_T_BOOL && PyBool_Check(input))
323 return Glib::Variant<bool>::create(input == Py_True);
324 else if (type == SR_T_FLOAT && PyFloat_Check(input))
325 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
326 else if (type == SR_T_INT32 && PyInt_Check(input))
327 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
329 throw sigrok::Error(SR_ERR_ARG);
332 /* Convert from a Python type to Glib::Variant, according to Option data type. */
333 Glib::VariantBase python_to_variant_by_option(PyObject *input,
334 std::shared_ptr<sigrok::Option> option)
336 GVariantType *type = option->default_value().get_type().gobj();
338 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
339 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
340 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
341 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
342 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
343 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
344 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
345 return Glib::Variant<bool>::create(input == Py_True);
346 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
347 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
348 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
349 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
351 throw sigrok::Error(SR_ERR_ARG);
354 /* Convert from a Python dict to a std::map<std::string, std::string> */
355 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
356 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
358 if (!PyDict_Check(dict))
359 throw sigrok::Error(SR_ERR_ARG);
361 std::map<std::string, Glib::VariantBase> output;
363 PyObject *py_key, *py_value;
366 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
367 if (!PyString_Check(py_key))
368 throw sigrok::Error(SR_ERR_ARG);
369 auto key = PyString_AsString(py_key);
370 auto value = python_to_variant_by_option(py_value, options[key]);
379 /* Ignore these methods, we will override them below. */
380 %ignore sigrok::Analog::data;
381 %ignore sigrok::Driver::scan;
382 %ignore sigrok::InputFormat::create_input;
383 %ignore sigrok::OutputFormat::create_output;
387 %define %attributevector(Class, Type, Name, Get)
388 %rename(_ ## Get) sigrok::Class::Get;
389 %extend sigrok::Class
393 Name = property(_ ## Get)
398 %define %attributemap(Class, Type, Name, Get)
399 %rename(_ ## Get) sigrok::Class::Get;
400 %extend sigrok::Class
404 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
409 %define %enumextras(Class)
410 %extend sigrok::Class
419 def __eq__(self, other):
420 return (type(self) is type(other) and hash(self) == hash(other))
422 def __ne__(self, other):
423 return (type(self) is not type(other) or hash(self) != hash(other))
428 %include "../../../swig/classes.i"
430 /* Support Driver.scan() with keyword arguments. */
431 %extend sigrok::Driver
433 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
435 if (!PyDict_Check(dict))
436 throw sigrok::Error(SR_ERR_ARG);
438 PyObject *py_key, *py_value;
440 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
442 while (PyDict_Next(dict, &pos, &py_key, &py_value))
444 if (!PyString_Check(py_key))
445 throw sigrok::Error(SR_ERR_ARG);
446 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
447 auto value = python_to_variant_by_key(py_value, key);
448 options[key] = value;
451 return $self->scan(options);
457 def _Driver_scan(self, **kwargs):
458 return self._scan_kwargs(kwargs)
460 Driver.scan = _Driver_scan
463 /* Support InputFormat.create_input() with keyword arguments. */
464 %extend sigrok::InputFormat
466 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
468 return $self->create_input(
469 dict_to_map_options(dict, $self->options()));
475 def _InputFormat_create_input(self, **kwargs):
476 return self._create_input(kwargs)
478 InputFormat.create_input = _InputFormat_create_input
481 /* Support OutputFormat.create_output() with keyword arguments. */
482 %extend sigrok::OutputFormat
484 std::shared_ptr<sigrok::Output> _create_output_kwargs(
485 std::shared_ptr<sigrok::Device> device, PyObject *dict)
487 return $self->create_output(device,
488 dict_to_map_options(dict, $self->options()));
494 def _OutputFormat_create_output(self, device, **kwargs):
495 return self._create_output_kwargs(device, kwargs)
497 OutputFormat.create_output = _OutputFormat_create_output
500 /* Support config_set() with Python input types. */
501 %extend sigrok::Configurable
503 void config_set(const ConfigKey *key, PyObject *input)
505 $self->config_set(key, python_to_variant_by_key(input, key));
509 /* Return NumPy array from Analog::data(). */
510 %extend sigrok::Analog
516 dims[0] = $self->channels().size();
517 dims[1] = $self->num_samples();
518 int typenum = NPY_FLOAT;
519 void *data = $self->data_pointer();
520 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
525 data = property(_data)