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;
54 PyTypeObject *IOChannel;
59 #if PYGOBJECT_FLAGS_SIGNED
60 typedef gint pyg_flags_type;
62 typedef guint pyg_flags_type;
68 PyGObject_lib = pygobject_init(-1, -1, -1);
70 fprintf(stderr, "pygobject initialization failed.\n");
71 GLib = PyImport_ImportModule("gi.repository.GLib");
73 * This check can't save us if the import fails, but at least it gives us
74 * a starting point to trace the issue versus straight out crashing.
77 fprintf(stderr, "Import of gi.repository.GLib failed.\n");
78 #if PY_VERSION_HEX >= 0x03000000
84 IOChannel = (PyTypeObject *) PyObject_GetAttrString(GLib, "IOChannel");
85 PollFD = (PyTypeObject *) PyObject_GetAttrString(GLib, "PollFD");
89 /* Map file objects to file descriptors. */
90 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
91 $1 = (PyObject_AsFileDescriptor($input) != -1);
95 int fd = PyObject_AsFileDescriptor($input);
97 SWIG_exception(SWIG_TypeError,
98 "Expected file object or integer file descriptor");
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"),
111 const_cast<char *>(""), NULL);
116 /* Map from Glib::IOCondition to GLib.IOCondition. */
117 %typecheck(SWIG_TYPECHECK_POINTER) Glib::IOCondition {
118 pyg_flags_type flags;
119 $1 = pygobject_check($input, &PyGFlags_Type) &&
120 (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) != -1);
123 %typemap(in) Glib::IOCondition {
124 if (!pygobject_check($input, &PyGFlags_Type))
125 SWIG_exception(SWIG_TypeError, "Expected GLib.IOCondition value");
126 pyg_flags_type flags;
127 if (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) == -1)
128 SWIG_exception(SWIG_TypeError, "Not a valid Glib.IOCondition value");
129 $1 = (Glib::IOCondition) flags;
133 %typemap(out) Glib::IOCondition {
134 GValue *value = g_new0(GValue, 1);
135 g_value_init(value, G_TYPE_IO_CONDITION);
136 g_value_set_flags(value, &$1);
137 $result = pyg_value_as_pyobject(value, true);
141 /* Map from GLib.PollFD to Glib::PollFD *. */
142 %typecheck(SWIG_TYPECHECK_POINTER) Glib::PollFD {
143 $1 = pygobject_check($input, PollFD);
146 %typemap(in) Glib::PollFD {
147 if (!pygobject_check($input, PollFD))
148 SWIG_exception(SWIG_TypeError, "Expected GLib.PollFD");
149 PyObject *fd_obj = PyObject_GetAttrString($input, "fd");
150 PyObject *events_obj = PyObject_GetAttrString($input, "events");
151 pyg_flags_type flags;
152 pyg_flags_get_value(G_TYPE_IO_CONDITION, events_obj, &flags);
153 int fd = PyInt_AsLong(fd_obj);
154 Glib::IOCondition events = (Glib::IOCondition) flags;
155 $1 = Glib::PollFD(fd, events);
158 /* Map from GLib.IOChannel to Glib::IOChannel *. */
159 %typecheck(SWIG_TYPECHECK_POINTER) Glib::RefPtr<Glib::IOChannel> {
160 $1 = pygobject_check($input, IOChannel);
163 %typemap(in) Glib::RefPtr<Glib::IOChannel> {
164 if (!pygobject_check($input, IOChannel))
165 SWIG_exception(SWIG_TypeError, "Expected GLib.IOChannel");
166 $1 = Glib::wrap((GIOChannel *) PyObject_Hash($input), true);
169 /* Map from callable PyObject to SourceCallbackFunction. */
170 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SourceCallbackFunction {
171 $1 = PyCallable_Check($input);
174 %typemap(in) sigrok::SourceCallbackFunction {
175 if (!PyCallable_Check($input))
176 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
178 $1 = [=] (Glib::IOCondition revents) {
179 auto gstate = PyGILState_Ensure();
181 GValue *value = g_new0(GValue, 1);
182 g_value_init(value, G_TYPE_IO_CONDITION);
183 g_value_set_flags(value, revents);
184 auto revents_obj = pyg_value_as_pyobject(value, true);
187 auto arglist = Py_BuildValue("(O)", revents_obj);
189 auto result = PyEval_CallObject($input, arglist);
192 Py_XDECREF(revents_obj);
194 bool completed = !PyErr_Occurred();
199 bool valid_result = (completed && PyBool_Check(result));
201 if (completed && !valid_result)
203 PyErr_SetString(PyExc_TypeError,
204 "EventSource callback did not return a boolean");
208 bool retval = (valid_result && result == Py_True);
212 PyGILState_Release(gstate);
215 throw sigrok::Error(SR_ERR);
223 /* Map from callable PyObject to LogCallbackFunction */
224 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
225 $1 = PyCallable_Check($input);
228 %typemap(in) sigrok::LogCallbackFunction {
229 if (!PyCallable_Check($input))
230 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
232 $1 = [=] (const sigrok::LogLevel *loglevel, std::string message) {
233 auto gstate = PyGILState_Ensure();
235 auto log_obj = SWIG_NewPointerObj(
236 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
238 auto string_obj = PyString_FromString(message.c_str());
240 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
242 auto result = PyEval_CallObject($input, arglist);
246 Py_XDECREF(string_obj);
248 bool completed = !PyErr_Occurred();
253 bool valid_result = (completed && result == Py_None);
257 if (completed && !valid_result)
259 PyErr_SetString(PyExc_TypeError,
260 "Log callback did not return None");
264 PyGILState_Release(gstate);
267 throw sigrok::Error(SR_ERR);
273 /* Map from callable PyObject to DatafeedCallbackFunction */
274 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
275 $1 = PyCallable_Check($input);
278 %typemap(in) sigrok::DatafeedCallbackFunction {
279 if (!PyCallable_Check($input))
280 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
282 $1 = [=] (std::shared_ptr<sigrok::Device> device,
283 std::shared_ptr<sigrok::Packet> packet) {
284 auto gstate = PyGILState_Ensure();
286 auto device_obj = SWIG_NewPointerObj(
287 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
288 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
290 auto packet_obj = SWIG_NewPointerObj(
291 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
292 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
294 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
296 auto result = PyEval_CallObject($input, arglist);
299 Py_XDECREF(device_obj);
300 Py_XDECREF(packet_obj);
302 bool completed = !PyErr_Occurred();
307 bool valid_result = (completed && result == Py_None);
311 if (completed && !valid_result)
313 PyErr_SetString(PyExc_TypeError,
314 "Datafeed callback did not return None");
318 PyGILState_Release(gstate);
321 throw sigrok::Error(SR_ERR);
327 /* Cast PacketPayload pointers to correct subclass type. */
328 %ignore sigrok::Packet::payload;
330 %extend sigrok::Packet
332 std::shared_ptr<sigrok::Header> _payload_header()
334 return dynamic_pointer_cast<sigrok::Header>($self->payload());
336 std::shared_ptr<sigrok::Meta> _payload_meta()
338 return dynamic_pointer_cast<sigrok::Meta>($self->payload());
340 std::shared_ptr<sigrok::Analog> _payload_analog()
342 return dynamic_pointer_cast<sigrok::Analog>($self->payload());
344 std::shared_ptr<sigrok::Logic> _payload_logic()
346 return dynamic_pointer_cast<sigrok::Logic>($self->payload());
350 %extend sigrok::Packet
355 if self.type == PacketType.HEADER:
356 return self._payload_header()
357 elif self.type == PacketType.META:
358 return self._payload_meta()
359 elif self.type == PacketType.LOGIC:
360 return self._payload_logic()
361 elif self.type == PacketType.ANALOG:
362 return self._payload_analog()
366 payload = property(_payload)
372 #include "libsigrokcxx/libsigrokcxx.hpp"
374 /* Convert from a Python dict to a std::map<std::string, std::string> */
375 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
377 if (!PyDict_Check(dict))
378 throw sigrok::Error(SR_ERR_ARG);
380 std::map<std::string, std::string> output;
382 PyObject *py_key, *py_value;
385 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
386 if (!PyString_Check(py_key))
387 throw sigrok::Error(SR_ERR_ARG);
388 if (!PyString_Check(py_value))
389 throw sigrok::Error(SR_ERR_ARG);
390 auto key = PyString_AsString(py_key);
391 auto value = PyString_AsString(py_value);
398 /* Convert from a Python type to Glib::Variant, according to config key data type. */
399 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
401 enum sr_datatype type = (enum sr_datatype) key->data_type()->id();
403 if (type == SR_T_UINT64 && PyInt_Check(input))
404 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
405 if (type == SR_T_UINT64 && PyLong_Check(input))
406 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
407 else if (type == SR_T_STRING && PyString_Check(input))
408 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
409 else if (type == SR_T_BOOL && PyBool_Check(input))
410 return Glib::Variant<bool>::create(input == Py_True);
411 else if (type == SR_T_FLOAT && PyFloat_Check(input))
412 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
413 else if (type == SR_T_INT32 && PyInt_Check(input))
414 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
416 throw sigrok::Error(SR_ERR_ARG);
419 /* Convert from a Python type to Glib::Variant, according to Option data type. */
420 Glib::VariantBase python_to_variant_by_option(PyObject *input,
421 std::shared_ptr<sigrok::Option> option)
423 GVariantType *type = option->default_value().get_type().gobj();
425 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
426 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
427 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
428 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
429 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
430 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
431 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
432 return Glib::Variant<bool>::create(input == Py_True);
433 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
434 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
435 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
436 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
438 throw sigrok::Error(SR_ERR_ARG);
441 /* Convert from a Python dict to a std::map<std::string, std::string> */
442 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
443 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
445 if (!PyDict_Check(dict))
446 throw sigrok::Error(SR_ERR_ARG);
448 std::map<std::string, Glib::VariantBase> output;
450 PyObject *py_key, *py_value;
453 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
454 if (!PyString_Check(py_key))
455 throw sigrok::Error(SR_ERR_ARG);
456 auto key = PyString_AsString(py_key);
457 auto value = python_to_variant_by_option(py_value, options[key]);
466 /* Ignore these methods, we will override them below. */
467 %ignore sigrok::Analog::data;
468 %ignore sigrok::Driver::scan;
469 %ignore sigrok::InputFormat::create_input;
470 %ignore sigrok::OutputFormat::create_output;
474 %define %attributevector(Class, Type, Name, Get)
475 %rename(_ ## Get) sigrok::Class::Get;
476 %extend sigrok::Class
480 Name = property(_ ## Get)
485 %define %attributemap(Class, Type, Name, Get)
486 %rename(_ ## Get) sigrok::Class::Get;
487 %extend sigrok::Class
491 Name = property(fget = lambda x: x._ ## Get().asdict(), doc=_ ## Get.__doc__)
496 %define %enumextras(Class)
497 %extend sigrok::Class
506 def __eq__(self, other):
507 return (type(self) is type(other) and hash(self) == hash(other))
509 def __ne__(self, other):
510 return (type(self) is not type(other) or hash(self) != hash(other))
515 %include "../../../swig/classes.i"
517 /* Support Driver.scan() with keyword arguments. */
518 %extend sigrok::Driver
520 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
522 if (!PyDict_Check(dict))
523 throw sigrok::Error(SR_ERR_ARG);
525 PyObject *py_key, *py_value;
527 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
529 while (PyDict_Next(dict, &pos, &py_key, &py_value))
531 if (!PyString_Check(py_key))
532 throw sigrok::Error(SR_ERR_ARG);
533 auto key = sigrok::ConfigKey::get_by_identifier(PyString_AsString(py_key));
534 auto value = python_to_variant_by_key(py_value, key);
535 options[key] = value;
538 return $self->scan(options);
544 def _Driver_scan(self, **kwargs):
545 return self._scan_kwargs(kwargs)
547 Driver.scan = _Driver_scan
550 /* Support InputFormat.create_input() with keyword arguments. */
551 %extend sigrok::InputFormat
553 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
555 return $self->create_input(
556 dict_to_map_options(dict, $self->options()));
562 def _InputFormat_create_input(self, **kwargs):
563 return self._create_input(kwargs)
565 InputFormat.create_input = _InputFormat_create_input
568 /* Support OutputFormat.create_output() with keyword arguments. */
569 %extend sigrok::OutputFormat
571 std::shared_ptr<sigrok::Output> _create_output_kwargs(
572 std::shared_ptr<sigrok::Device> device, PyObject *dict)
574 return $self->create_output(device,
575 dict_to_map_options(dict, $self->options()));
581 def _OutputFormat_create_output(self, device, **kwargs):
582 return self._create_output_kwargs(device, kwargs)
584 OutputFormat.create_output = _OutputFormat_create_output
587 /* Support config_set() with Python input types. */
588 %extend sigrok::Configurable
590 void config_set(const ConfigKey *key, PyObject *input)
592 $self->config_set(key, python_to_variant_by_key(input, key));
596 /* Return NumPy array from Analog::data(). */
597 %extend sigrok::Analog
603 dims[0] = $self->channels().size();
604 dims[1] = $self->num_samples();
605 int typenum = NPY_FLOAT;
606 void *data = $self->data_pointer();
607 return PyArray_SimpleNewFromData(nd, dims, typenum, data);
612 data = property(_data)