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;
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 /* Map from callable PyObject to LogCallbackFunction */
116 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
117 $1 = PyCallable_Check($input);
120 %typemap(in) sigrok::LogCallbackFunction {
121 if (!PyCallable_Check($input))
122 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
124 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
125 auto gstate = PyGILState_Ensure();
127 auto log_obj = SWIG_NewPointerObj(
128 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
130 auto string_obj = string_to_python(message.c_str());
132 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
134 auto result = PyEval_CallObject($input, arglist);
138 Py_XDECREF(string_obj);
140 bool completed = !PyErr_Occurred();
145 bool valid_result = (completed && result == Py_None);
149 if (completed && !valid_result)
151 PyErr_SetString(PyExc_TypeError,
152 "Log callback did not return None");
156 PyGILState_Release(gstate);
159 throw sigrok::Error(SR_ERR);
165 /* Map from callable PyObject to SessionStoppedCallback */
166 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SessionStoppedCallback {
167 $1 = PyCallable_Check($input);
170 %typemap(in) sigrok::SessionStoppedCallback {
171 if (!PyCallable_Check($input))
172 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
175 const auto gstate = PyGILState_Ensure();
177 const auto result = PyEval_CallObject($input, nullptr);
178 const bool completed = !PyErr_Occurred();
179 const bool valid_result = (completed && result == Py_None);
181 if (completed && !valid_result) {
182 PyErr_SetString(PyExc_TypeError,
183 "Session stop callback did not return None");
189 PyGILState_Release(gstate);
192 throw sigrok::Error(SR_ERR);
198 /* Map from callable PyObject to DatafeedCallbackFunction */
199 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
200 $1 = PyCallable_Check($input);
203 %typemap(in) sigrok::DatafeedCallbackFunction {
204 if (!PyCallable_Check($input))
205 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
207 $1 = [=] (std::shared_ptr<sigrok::Device> device,
208 std::shared_ptr<sigrok::Packet> packet) {
209 auto gstate = PyGILState_Ensure();
211 auto device_obj = SWIG_NewPointerObj(
212 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
213 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
215 auto packet_obj = SWIG_NewPointerObj(
216 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
217 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
219 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
221 auto result = PyEval_CallObject($input, arglist);
224 Py_XDECREF(device_obj);
225 Py_XDECREF(packet_obj);
227 bool completed = !PyErr_Occurred();
232 bool valid_result = (completed && result == Py_None);
236 if (completed && !valid_result)
238 PyErr_SetString(PyExc_TypeError,
239 "Datafeed callback did not return None");
243 PyGILState_Release(gstate);
246 throw sigrok::Error(SR_ERR);
252 /* Cast PacketPayload pointers to correct subclass type. */
253 %ignore sigrok::Packet::payload;
255 %extend sigrok::Packet
257 std::shared_ptr<sigrok::Header> _payload_header()
259 return dynamic_pointer_cast<sigrok::Header>($self->payload());
261 std::shared_ptr<sigrok::Meta> _payload_meta()
263 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
265 std::shared_ptr<sigrok::Analog> _payload_analog()
267 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
269 std::shared_ptr<sigrok::Logic> _payload_logic()
271 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
275 %extend sigrok::Packet
280 if self.type == PacketType.HEADER:
281 return self._payload_header()
282 elif self.type == PacketType.META:
283 return self._payload_meta()
284 elif self.type == PacketType.LOGIC:
285 return self._payload_logic()
286 elif self.type == PacketType.ANALOG:
287 return self._payload_analog()
291 payload = property(_payload)
297 #include "libsigrokcxx/libsigrokcxx.hpp"
299 /* Convert from a Python dict to a std::map<std::string, std::string> */
300 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
302 if (!PyDict_Check(dict))
303 throw sigrok::Error(SR_ERR_ARG);
305 std::map<std::string, std::string> output;
307 PyObject *py_key, *py_value;
310 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
311 if (!string_check(py_key))
312 throw sigrok::Error(SR_ERR_ARG);
313 if (!string_check(py_value))
314 throw sigrok::Error(SR_ERR_ARG);
315 auto key = string_from_python(py_key);
316 auto value = string_from_python(py_value);
323 /* Convert from a Python type to Glib::Variant, according to config key data type. */
324 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
326 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
328 if (type == SR_T_UINT64 && PyInt_Check(input))
329 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
330 if (type == SR_T_UINT64 && PyLong_Check(input))
331 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
332 else if (type == SR_T_STRING && string_check(input))
333 return Glib::Variant<Glib::ustring>::create(string_from_python(input));
334 else if (type == SR_T_BOOL && PyBool_Check(input))
335 return Glib::Variant<bool>::create(input == Py_True);
336 else if (type == SR_T_FLOAT && PyFloat_Check(input))
337 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
338 else if (type == SR_T_INT32 && PyInt_Check(input))
339 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
341 throw sigrok::Error(SR_ERR_ARG);
344 /* Convert from a Python type to Glib::Variant, according to Option data type. */
345 Glib::VariantBase python_to_variant_by_option(PyObject *input,
346 std::shared_ptr<sigrok::Option> option)
348 GVariantType *type = option->default_value().get_type().gobj();
350 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
351 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
352 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
353 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
354 else if (type == G_VARIANT_TYPE_STRING && string_check(input))
355 return Glib::Variant<Glib::ustring>::create(string_from_python(input));
356 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
357 return Glib::Variant<bool>::create(input == Py_True);
358 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
359 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
360 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
361 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
363 throw sigrok::Error(SR_ERR_ARG);
366 /* Convert from a Python dict to a std::map<std::string, std::string> */
367 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
368 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
370 if (!PyDict_Check(dict))
371 throw sigrok::Error(SR_ERR_ARG);
373 std::map<std::string, Glib::VariantBase> output;
375 PyObject *py_key, *py_value;
378 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
379 if (!string_check(py_key))
380 throw sigrok::Error(SR_ERR_ARG);
381 auto key = string_from_python(py_key);
382 auto value = python_to_variant_by_option(py_value, options[key]);
391 /* Ignore these methods, we will override them below. */
392 %ignore sigrok::Analog::data;
393 %ignore sigrok::Driver::scan;
394 %ignore sigrok::InputFormat::create_input;
395 %ignore sigrok::OutputFormat::create_output;
397 %include "doc_start.i"
399 %define %attributevector(Class, Type, Name, Get)
400 %rename(_ ## Get) sigrok::Class::Get;
401 %extend sigrok::Class
405 Name = property(_ ## Get)
410 %define %attributemap(Class, Type, Name, Get)
411 %rename(_ ## Get) sigrok::Class::Get;
412 %extend sigrok::Class
416 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
421 %define %enumextras(Class)
422 %extend sigrok::Class
429 std::string __str__()
431 return $self->name();
434 std::string __repr__()
436 return "Class." + $self->name();
441 def __eq__(self, other):
442 return (type(self) is type(other) and hash(self) == hash(other))
444 def __ne__(self, other):
445 return (type(self) is not type(other) or hash(self) != hash(other))
450 %include "../../../swig/classes.i"
452 /* Support Driver.scan() with keyword arguments. */
453 %extend sigrok::Driver
455 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
457 if (!PyDict_Check(dict))
458 throw sigrok::Error(SR_ERR_ARG);
460 PyObject *py_key, *py_value;
462 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
464 while (PyDict_Next(dict, &pos, &py_key, &py_value))
466 if (!string_check(py_key))
467 throw sigrok::Error(SR_ERR_ARG);
468 auto key = sigrok::ConfigKey::get_by_identifier(string_from_python(py_key));
469 auto value = python_to_variant_by_key(py_value, key);
470 options[key] = value;
473 return $self->scan(options);
479 def _Driver_scan(self, **kwargs):
480 return self._scan_kwargs(kwargs)
482 Driver.scan = _Driver_scan
485 /* Support InputFormat.create_input() with keyword arguments. */
486 %extend sigrok::InputFormat
488 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
490 return $self->create_input(
491 dict_to_map_options(dict, $self->options()));
497 def _InputFormat_create_input(self, **kwargs):
498 return self._create_input(kwargs)
500 InputFormat.create_input = _InputFormat_create_input
503 /* Support OutputFormat.create_output() with keyword arguments. */
504 %extend sigrok::OutputFormat
506 std::shared_ptr<sigrok::Output> _create_output_kwargs(
507 std::shared_ptr<sigrok::Device> device, PyObject *dict)
509 return $self->create_output(device,
510 dict_to_map_options(dict, $self->options()));
516 def _OutputFormat_create_output(self, device, **kwargs):
517 return self._create_output_kwargs(device, kwargs)
519 OutputFormat.create_output = _OutputFormat_create_output
522 /* Support config_set() with Python input types. */
523 %extend sigrok::Configurable
525 void config_set(const ConfigKey *key, PyObject *input)
527 $self->config_set(key, python_to_variant_by_key(input, key));
531 /* Return NumPy array from Analog::data(). */
532 %extend sigrok::Analog
538 dims[0] = $self->channels().size();
539 dims[1] = $self->num_samples();
540 int typenum = NPY_FLOAT;
541 void *data = $self->data_pointer();
542 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
547 data = property(_data)