--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!ENTITY % comedilib_entities SYSTEM "comedilib.ent">
+%comedilib_entities;
+]>
+<section id="languagebindings">
+ <title>Language bindings</title>
+ <para>
+ Comedilib is a C library but comes also with bindings for Python, Perl, and Ruby.
+ This enables usage of a DAQ device directly from these higher level languages.
+ </para>
+
+ <section id="pythonbindings">
+ <title>Python bindings</title>
+ <para>
+ Python bindings are automatically generated by SWIG. So always keep in mind that
+ for precise information the <ulink url="http://www.swig.org/Doc2.0/index.html">SWIG documentation</ulink>
+ can come in handy in addition to the &comedi; documentation.
+ </para>
+ <para>
+ The name of the module is called <filename>comedi</filename>. All the C functions, structs, and
+ constants are directly available as is. So you can refer directly to the C
+ documentation for most of the usage. Note that, as in C, the functions either return the
+ successful result or an error code. Unlike typical Python functions,
+ no exceptions are generated on errors (excepted type-checking
+ performed by SWIG). For example, to open a &comedi; device you can write in
+ Python:
+ <programlisting>
+import comedi
+device = comedi.comedi_open("/dev/comedi0")
+if device is None:
+ errno = comedi.comedi_errno()
+ print "Error (%d) %s" % (errno, comedi.comedi_strerror(errno))
+ return
+ </programlisting>
+ </para>
+ <para>
+ There are a few things to be aware of. The SWIG bindings automatically take care
+ of converting functions with output parameters to function returning multiple
+ values, if the type of the output parameter is simple. For example
+ <function>comedi_data_read</function> takes as argument a
+ <parameter class="function">lsampl_t *data</parameter> which will contain the data
+ read after the function returns. So in C it is used like this:
+ <programlisting><![CDATA[
+lsampl_t data;
+rc = comedi_data_read(device, subdevice, channel, range, aref, &data);
+ ]]></programlisting>
+
+ As <parameter class="function">lsampl_t</parameter> is a 32-bit
+ <parameter class="function">unsigned int</parameter>, in Python, the function is used like this:
+ <programlisting>
+rc, data = comedi.comedi_data_read(device, subdevice, channel, range, aref)
+ </programlisting>
+ </para>
+ <para>
+ SWIG takes care of converting simple types between Python and C, but does not
+ convert more complex types such as arrays or structs. Special Python classes are
+ created for these. Moreover, &comedi; also provides a few macros. These macros
+ are available in Python as functions with similar names, but lowercase: <function>comedi.cr_pack</function>,
+ <function>comedi.cr_range</function>, etc.
+ So to create and modify a command, one can do in Python:
+ <programlisting>
+cmd = comedi.comedi_cmd_struct()
+comedi.comedi_get_cmd_generic_timed(device, subdevice, cmd, nchans, period_ns)
+cmd.stop_src = comedi.TRIG_COUNT
+cmd.stop_arg = nscans
+# create and add the channel list
+clist = comedi.chanlist(nchans)
+for i, channel in range(nchans):
+ clist[i] = comedi.cr_pack(channel, range, comedi.AREF_GROUND)
+cmd.chanlist = clist
+ </programlisting>
+ </para>
+ <para>
+ One unfortunate consequence is that the objects to represent arrays are as low-level
+ as C arrays (i.e., a pointer with an addition). They have no range checking and
+ no iterator. In addition, they have to be <function>cast</function> from the Python object to the
+ C object. So to create an instruction to call the internal trigger, you would
+ write in Python:
+ <programlisting>
+insn = comedi.comedi_insn_struct()
+insn.subdev = subdevice
+insn.insn = comedi.INSN_INTTRIG
+insn.n = 1
+data = comedi.lsampl_array(insn.n)
+data[0] = num
+insn.data = data.cast()
+rc = comedi.comedi_do_insn(device, insn)
+ </programlisting>
+ </para>
+ <para>
+ When you need to convert from a raw SWIG object to a proxy
+ object, the <function>.frompointer</function> of the Python object can be used. Also note that by default
+ when the proxy object is deleted, SWIG frees the memory associated to it. To
+ still be able to use the memory, you need to set
+ <parameter class="function">.thisown</parameter> to <parameter class="function">False</parameter>.
+ </para>
+ <para>
+ Reading (or writing) a large set of data from a &comedi; device is done via a file.
+ In C, this is done by using a file number, but in Python you need a
+ <parameter class="function">File</parameter> object.
+ You can get a <parameter class="function">File</parameter> object via
+ <function>os.fdopen</function>. For example, to read an array of input data
+ from a &comedi; device into a numpy array, one could do:
+ <programlisting>
+fileno = comedi.comedi_fileno(device)
+file = os.fdopen(fileno, 'r+')
+buf = numpy.fromfile(file, dtype=numpy.uint32, count=(nscans * nchans))
+ </programlisting>
+ </para>
+ </section>
+</section>