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 sigrok++ 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
48 #include <pygobject.h>
51 PyTypeObject *IOChannel;
56 #if PYGOBJECT_FLAGS_SIGNED
57 typedef gint pyg_flags_type;
59 typedef guint pyg_flags_type;
65 pygobject_init(-1, -1, -1);
66 GLib = PyImport_ImportModule("gi.repository.GLib");
67 IOChannel = (PyTypeObject *) PyObject_GetAttrString(GLib, "IOChannel");
68 PollFD = (PyTypeObject *) PyObject_GetAttrString(GLib, "PollFD");
71 /* Map file objects to file descriptors. */
72 %typecheck(SWIG_TYPECHECK_POINTER) int fd {
73 $1 = (PyObject_AsFileDescriptor($input) != -1);
77 int fd = PyObject_AsFileDescriptor($input);
79 SWIG_exception(SWIG_TypeError,
80 "Expected file object or integer file descriptor");
85 /* Map from Glib::Variant to native Python types. */
86 %typemap(out) Glib::VariantBase {
87 GValue *value = g_new0(GValue, 1);
88 g_value_init(value, G_TYPE_VARIANT);
89 g_value_set_variant(value, $1.gobj());
90 PyObject *variant = pyg_value_as_pyobject(value, true);
91 $result = PyObject_CallMethod(variant,
92 const_cast<char *>("unpack"),
93 const_cast<char *>(""), NULL);
98 /* Map from Glib::IOCondition to GLib.IOCondition. */
99 %typecheck(SWIG_TYPECHECK_POINTER) Glib::IOCondition {
100 pyg_flags_type flags;
101 $1 = pygobject_check($input, &PyGFlags_Type) &&
102 (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) != -1);
105 %typemap(in) Glib::IOCondition {
106 if (!pygobject_check($input, &PyGFlags_Type))
107 SWIG_exception(SWIG_TypeError, "Expected GLib.IOCondition value");
108 pyg_flags_type flags;
109 if (pyg_flags_get_value(G_TYPE_IO_CONDITION, $input, &flags) == -1)
110 SWIG_exception(SWIG_TypeError, "Not a valid Glib.IOCondition value");
111 $1 = (Glib::IOCondition) flags;
115 %typemap(out) Glib::IOCondition {
116 GValue *value = g_new0(GValue, 1);
117 g_value_init(value, G_TYPE_IO_CONDITION);
118 g_value_set_flags(value, &$1);
119 $result = pyg_value_as_pyobject(value, true);
123 /* Map from GLib.PollFD to Glib::PollFD *. */
124 %typecheck(SWIG_TYPECHECK_POINTER) Glib::PollFD {
125 $1 = pygobject_check($input, PollFD);
128 %typemap(in) Glib::PollFD {
129 if (!pygobject_check($input, PollFD))
130 SWIG_exception(SWIG_TypeError, "Expected GLib.PollFD");
131 PyObject *fd_obj = PyObject_GetAttrString($input, "fd");
132 PyObject *events_obj = PyObject_GetAttrString($input, "events");
133 pyg_flags_type flags;
134 pyg_flags_get_value(G_TYPE_IO_CONDITION, events_obj, &flags);
135 int fd = PyInt_AsLong(fd_obj);
136 Glib::IOCondition events = (Glib::IOCondition) flags;
137 $1 = Glib::PollFD(fd, events);
140 /* Map from GLib.IOChannel to Glib::IOChannel *. */
141 %typecheck(SWIG_TYPECHECK_POINTER) Glib::RefPtr<Glib::IOChannel> {
142 $1 = pygobject_check($input, IOChannel);
145 %typemap(in) Glib::RefPtr<Glib::IOChannel> {
146 if (!pygobject_check($input, IOChannel))
147 SWIG_exception(SWIG_TypeError, "Expected GLib.IOChannel");
148 $1 = Glib::wrap((GIOChannel *) PyObject_Hash($input), true);
151 /* Map from callable PyObject to SourceCallbackFunction. */
152 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::SourceCallbackFunction {
153 $1 = PyCallable_Check($input);
156 %typemap(in) sigrok::SourceCallbackFunction {
157 if (!PyCallable_Check($input))
158 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
160 $1 = [=] (Glib::IOCondition revents) {
161 auto gstate = PyGILState_Ensure();
163 GValue *value = g_new0(GValue, 1);
164 g_value_init(value, G_TYPE_IO_CONDITION);
165 g_value_set_flags(value, revents);
166 auto revents_obj = pyg_value_as_pyobject(value, true);
169 auto arglist = Py_BuildValue("(O)", revents_obj);
171 auto result = PyEval_CallObject($input, arglist);
174 Py_XDECREF(revents_obj);
176 if (PyErr_Occurred() || !PyBool_Check(result))
177 throw sigrok::Error(SR_ERR);
179 bool retval = (result == Py_True);
183 PyGILState_Release(gstate);
191 /* Map from callable PyObject to LogCallbackFunction */
192 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
193 $1 = PyCallable_Check($input);
196 %typemap(in) sigrok::LogCallbackFunction {
197 if (!PyCallable_Check($input))
198 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
200 $1 = [=] (const sigrok::LogLevel *loglevel, string message) {
201 auto gstate = PyGILState_Ensure();
203 auto log_obj = SWIG_NewPointerObj(
204 SWIG_as_voidptr(loglevel), SWIGTYPE_p_sigrok__LogLevel, 0);
206 auto string_obj = PyString_FromString(message.c_str());
208 auto arglist = Py_BuildValue("(OO)", log_obj, string_obj);
210 auto result = PyEval_CallObject($input, arglist);
214 Py_XDECREF(string_obj);
217 PyGILState_Release(gstate);
223 /* Map from callable PyObject to DatafeedCallbackFunction */
224 %typecheck(SWIG_TYPECHECK_POINTER) sigrok::DatafeedCallbackFunction {
225 $1 = PyCallable_Check($input);
228 %typemap(in) sigrok::DatafeedCallbackFunction {
229 if (!PyCallable_Check($input))
230 SWIG_exception(SWIG_TypeError, "Expected a callable Python object");
232 $1 = [=] (std::shared_ptr<sigrok::Device> device,
233 std::shared_ptr<sigrok::Packet> packet) {
234 auto gstate = PyGILState_Ensure();
236 auto device_obj = SWIG_NewPointerObj(
237 SWIG_as_voidptr(new std::shared_ptr<sigrok::Device>(device)),
238 SWIGTYPE_p_std__shared_ptrT_sigrok__Device_t, SWIG_POINTER_OWN);
240 auto packet_obj = SWIG_NewPointerObj(
241 SWIG_as_voidptr(new std::shared_ptr<sigrok::Packet>(packet)),
242 SWIGTYPE_p_std__shared_ptrT_sigrok__Packet_t, SWIG_POINTER_OWN);
244 auto arglist = Py_BuildValue("(OO)", device_obj, packet_obj);
246 auto result = PyEval_CallObject($input, arglist);
249 Py_XDECREF(device_obj);
250 Py_XDECREF(packet_obj);
253 PyGILState_Release(gstate);
261 #include "libsigrok/libsigrok.hpp"
263 /* Convert from a Python dict to a std::map<std::string, std::string> */
264 std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
266 if (!PyDict_Check(dict))
267 throw sigrok::Error(SR_ERR_ARG);
269 std::map<std::string, std::string> output;
271 PyObject *py_key, *py_value;
274 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
275 if (!PyString_Check(py_key))
276 throw sigrok::Error(SR_ERR_ARG);
277 if (!PyString_Check(py_value))
278 throw sigrok::Error(SR_ERR_ARG);
279 auto key = PyString_AsString(py_key);
280 auto value = PyString_AsString(py_value);
287 /* Convert from a Python type to Glib::Variant, according to config key data type. */
288 Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::ConfigKey *key)
290 enum sr_datatype type = key->data_type()->id();
292 if (type == SR_T_UINT64 && PyInt_Check(input))
293 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
294 if (type == SR_T_UINT64 && PyLong_Check(input))
295 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
296 else if (type == SR_T_STRING && PyString_Check(input))
297 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
298 else if (type == SR_T_BOOL && PyBool_Check(input))
299 return Glib::Variant<bool>::create(input == Py_True);
300 else if (type == SR_T_FLOAT && PyFloat_Check(input))
301 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
302 else if (type == SR_T_INT32 && PyInt_Check(input))
303 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
305 throw sigrok::Error(SR_ERR_ARG);
308 /* Convert from a Python type to Glib::Variant, according to Option data type. */
309 Glib::VariantBase python_to_variant_by_option(PyObject *input,
310 std::shared_ptr<sigrok::Option> option)
312 GVariantType *type = option->default_value().get_type().gobj();
314 if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
315 return Glib::Variant<guint64>::create(PyInt_AsLong(input));
316 if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
317 return Glib::Variant<guint64>::create(PyLong_AsLong(input));
318 else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
319 return Glib::Variant<Glib::ustring>::create(PyString_AsString(input));
320 else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
321 return Glib::Variant<bool>::create(input == Py_True);
322 else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
323 return Glib::Variant<double>::create(PyFloat_AsDouble(input));
324 else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
325 return Glib::Variant<gint32>::create(PyInt_AsLong(input));
327 throw sigrok::Error(SR_ERR_ARG);
330 /* Convert from a Python dict to a std::map<std::string, std::string> */
331 std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
332 std::map<std::string, std::shared_ptr<sigrok::Option> > options)
334 if (!PyDict_Check(dict))
335 throw sigrok::Error(SR_ERR_ARG);
337 std::map<std::string, Glib::VariantBase> output;
339 PyObject *py_key, *py_value;
342 while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
343 if (!PyString_Check(py_key))
344 throw sigrok::Error(SR_ERR_ARG);
345 auto key = PyString_AsString(py_key);
346 auto value = python_to_variant_by_option(py_value, options[key]);
355 /* Ignore these methods, we will override them below. */
356 %ignore sigrok::Driver::scan;
357 %ignore sigrok::InputFormat::create_input;
358 %ignore sigrok::OutputFormat::create_output;
362 %include "../../../swig/classes.i"
364 /* Support Driver.scan() with keyword arguments. */
365 %extend sigrok::Driver
367 std::vector<std::shared_ptr<sigrok::HardwareDevice> > _scan_kwargs(PyObject *dict)
369 if (!PyDict_Check(dict))
370 throw sigrok::Error(SR_ERR_ARG);
372 PyObject *py_key, *py_value;
374 std::map<const sigrok::ConfigKey *, Glib::VariantBase> options;
376 while (PyDict_Next(dict, &pos, &py_key, &py_value))
378 if (!PyString_Check(py_key))
379 throw sigrok::Error(SR_ERR_ARG);
380 auto key = sigrok::ConfigKey::get(PyString_AsString(py_key));
381 auto value = python_to_variant_by_key(py_value, key);
382 options[key] = value;
385 return $self->scan(options);
391 def _Driver_scan(self, **kwargs):
392 return self._scan_kwargs(kwargs)
394 Driver.scan = _Driver_scan
397 /* Support InputFormat.create_input() with keyword arguments. */
398 %extend sigrok::InputFormat
400 std::shared_ptr<sigrok::Input> _create_input_kwargs(PyObject *dict)
402 return $self->create_input(
403 dict_to_map_options(dict, $self->options()));
409 def _InputFormat_create_input(self, **kwargs):
410 return self._create_input(kwargs)
412 InputFormat.create_input = _InputFormat_create_input
415 /* Support OutputFormat.create_output() with keyword arguments. */
416 %extend sigrok::OutputFormat
418 std::shared_ptr<sigrok::Output> _create_output_kwargs(
419 std::shared_ptr<sigrok::Device> device, PyObject *dict)
421 return $self->create_output(device,
422 dict_to_map_options(dict, $self->options()));
428 def _OutputFormat_create_output(self, device, **kwargs):
429 return self._create_output_kwargs(device, kwargs)
431 OutputFormat.create_output = _OutputFormat_create_output
434 /* Support config_set() with Python input types. */
435 %extend sigrok::Configurable
437 void config_set(const ConfigKey *key, PyObject *input)
439 $self->config_set(key, python_to_variant_by_key(input, key));