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 DatafeedCallbackFunction */
154 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
155 $1 = PyCallable_Check($input);
158 %typemap(in) sigrok::DatafeedCallbackFunction {
159 if (!PyCallable_Check($input))
160 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
162 $1 = [=] (std::shared_ptr<sigrok::Device> device,
163 std::shared_ptr<sigrok::Packet> packet) {
164 auto gstate = PyGILState_Ensure();
166 auto device_obj = SWIG_NewPointerObj(
167 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
168 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
170 auto packet_obj = SWIG_NewPointerObj(
171 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
172 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
174 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
176 auto result = PyEval_CallObject($input, arglist);
179 Py_XDECREF(device_obj);
180 Py_XDECREF(packet_obj);
182 bool completed = !PyErr_Occurred();
187 bool valid_result = (completed && result == Py_None);
191 if (completed && !valid_result)
193 PyErr_SetString(PyExc_TypeError,
194 "Datafeed callback did not return None");
198 PyGILState_Release(gstate);
201 throw sigrok::Error(SR_ERR);
207 /* Cast PacketPayload pointers to correct subclass type. */
208 %ignore sigrok::Packet::payload;
210 %extend sigrok::Packet
212 std::shared_ptr<sigrok::Header> _payload_header()
214 return dynamic_pointer_cast<sigrok::Header>($self->payload());
216 std::shared_ptr<sigrok::Meta> _payload_meta()
218 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
220 std::shared_ptr<sigrok::Analog> _payload_analog()
222 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
224 std::shared_ptr<sigrok::Logic> _payload_logic()
226 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
230 %extend sigrok::Packet
235 if self.type == PacketType.HEADER:
236 return self._payload_header()
237 elif self.type == PacketType.META:
238 return self._payload_meta()
239 elif self.type == PacketType.LOGIC:
240 return self._payload_logic()
241 elif self.type == PacketType.ANALOG:
242 return self._payload_analog()
246 payload = property(_payload)
252 #include "libsigrokcxx/libsigrokcxx.hpp"
254 /* Convert from a Python dict to a std::map<std::string, std::string> */
255 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
257 if (!PyDict_Check(dict))
258 throw sigrok::Error(SR_ERR_ARG);
260 std::map<std::string, std::string> output;
262 PyObject *py_key, *py_value;
265 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
266 if (!PyString_Check(py_key))
267 throw sigrok::Error(SR_ERR_ARG);
268 if (!PyString_Check(py_value))
269 throw sigrok::Error(SR_ERR_ARG);
270 auto key = PyString_AsString(py_key);
271 auto value = PyString_AsString(py_value);
278 /* Convert from a Python type to Glib::Variant, according to config key data type. */
279 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
281 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
283 if (type == SR_T_UINT64 && PyInt_Check(input))
284 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
285 if (type == SR_T_UINT64 && PyLong_Check(input))
286 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
287 else if (type == SR_T_STRING && PyString_Check(input))
288 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
289 else if (type == SR_T_BOOL && PyBool_Check(input))
290 return Glib::Variant<bool>::create(input == Py_True);
291 else if (type == SR_T_FLOAT && PyFloat_Check(input))
292 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
293 else if (type == SR_T_INT32 && PyInt_Check(input))
294 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
296 throw sigrok::Error(SR_ERR_ARG);
299 /* Convert from a Python type to Glib::Variant, according to Option data type. */
300 Glib::VariantBase python_to_variant_by_option(PyObject *input,
301 std::shared_ptr<sigrok::Option> option)
303 GVariantType *type = option->default_value().get_type().gobj();
305 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
306 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
307 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
308 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
309 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
310 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
311 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
312 return Glib::Variant<bool>::create(input == Py_True);
313 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
314 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
315 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
316 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
318 throw sigrok::Error(SR_ERR_ARG);
321 /* Convert from a Python dict to a std::map<std::string, std::string> */
322 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
323 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
325 if (!PyDict_Check(dict))
326 throw sigrok::Error(SR_ERR_ARG);
328 std::map<std::string, Glib::VariantBase> output;
330 PyObject *py_key, *py_value;
333 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
334 if (!PyString_Check(py_key))
335 throw sigrok::Error(SR_ERR_ARG);
336 auto key = PyString_AsString(py_key);
337 auto value = python_to_variant_by_option(py_value, options[key]);
346 /* Ignore these methods, we will override them below. */
347 %ignore sigrok::Analog::data;
348 %ignore sigrok::Driver::scan;
349 %ignore sigrok::InputFormat::create_input;
350 %ignore sigrok::OutputFormat::create_output;
354 %define %attributevector(Class, Type, Name, Get)
355 %rename(_ ## Get) sigrok::Class::Get;
356 %extend sigrok::Class
360 Name = property(_ ## Get)
365 %define %attributemap(Class, Type, Name, Get)
366 %rename(_ ## Get) sigrok::Class::Get;
367 %extend sigrok::Class
371 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
376 %define %enumextras(Class)
377 %extend sigrok::Class
386 def __eq__(self, other):
387 return (type(self) is type(other) and hash(self) == hash(other))
389 def __ne__(self, other):
390 return (type(self) is not type(other) or hash(self) != hash(other))
395 %include "../../../swig/classes.i"
397 /* Support Driver.scan() with keyword arguments. */
398 %extend sigrok::Driver
400 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
402 if (!PyDict_Check(dict))
403 throw sigrok::Error(SR_ERR_ARG);
405 PyObject *py_key, *py_value;
407 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
409 while (PyDict_Next(dict, &pos, &py_key, &py_value))
411 if (!PyString_Check(py_key))
412 throw sigrok::Error(SR_ERR_ARG);
413 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
414 auto value = python_to_variant_by_key(py_value, key);
415 options[key] = value;
418 return $self->scan(options);
424 def _Driver_scan(self, **kwargs):
425 return self._scan_kwargs(kwargs)
427 Driver.scan = _Driver_scan
430 /* Support InputFormat.create_input() with keyword arguments. */
431 %extend sigrok::InputFormat
433 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
435 return $self->create_input(
436 dict_to_map_options(dict, $self->options()));
442 def _InputFormat_create_input(self, **kwargs):
443 return self._create_input(kwargs)
445 InputFormat.create_input = _InputFormat_create_input
448 /* Support OutputFormat.create_output() with keyword arguments. */
449 %extend sigrok::OutputFormat
451 std::shared_ptr<sigrok::Output> _create_output_kwargs(
452 std::shared_ptr<sigrok::Device> device, PyObject *dict)
454 return $self->create_output(device,
455 dict_to_map_options(dict, $self->options()));
461 def _OutputFormat_create_output(self, device, **kwargs):
462 return self._create_output_kwargs(device, kwargs)
464 OutputFormat.create_output = _OutputFormat_create_output
467 /* Support config_set() with Python input types. */
468 %extend sigrok::Configurable
470 void config_set(const ConfigKey *key, PyObject *input)
472 $self->config_set(key, python_to_variant_by_key(input, key));
476 /* Return NumPy array from Analog::data(). */
477 %extend sigrok::Analog
483 dims[0] = $self->channels().size();
484 dims[1] = $self->num_samples();
485 int typenum = NPY_FLOAT;
486 void *data = $self->data_pointer();
487 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
492 data = property(_data)