From: Éric Piel Date: Mon, 29 Oct 2012 17:08:09 +0000 (+0000) Subject: doc: add a section about Python bindings X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=7d4ad9ad15b9cd8620c987712fbaa38dc51b513f;p=comedilib.git doc: add a section about Python bindings This section goes into a "Language bindings" section where description for Perl and Ruby could also go. --- diff --git a/doc/Makefile.am b/doc/Makefile.am index ac79726..bad00b2 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -3,7 +3,7 @@ XML = calibration_funcref.xml command_funcref.xml dio_funcref.xml \ deprecated_funcref.xml error_funcref.xml extensions_funcref.xml \ drivers.xml funcref.xml glossary.xml \ install.xml intro.xml other.xml reference.xml tutorial.xml \ - driverwriting.xml comedilib.xml comedilib.ent + driverwriting.xml comedilib.xml bindings.xml comedilib.ent EXTRA_DIST = $(XML) calibration_funcref.txt command_funcref.txt dio_funcref.txt \ deprecated_funcref.txt error_funcref.txt extensions_funcref.txt \ @@ -14,7 +14,7 @@ EXTRA_DIST = $(XML) calibration_funcref.txt command_funcref.txt dio_funcref.txt BUILT_SOURCES = calibration_funcref.xml command_funcref.xml dio_funcref.xml \ deprecated_funcref.xml error_funcref.xml extensions_funcref.xml \ - funcref.xml drivers.xml + funcref.xml drivers.xml bindings.xml if HAVE_XMLTO all_html = $(srcdir)/doc_html diff --git a/doc/bindings.xml b/doc/bindings.xml new file mode 100644 index 0000000..67de562 --- /dev/null +++ b/doc/bindings.xml @@ -0,0 +1,113 @@ + + +%comedilib_entities; +]> +
+ Language bindings + + 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. + + +
+ Python bindings + + Python bindings are automatically generated by SWIG. So always keep in mind that + for precise information the SWIG documentation + can come in handy in addition to the &comedi; documentation. + + + The name of the module is called comedi. 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: + +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 + + + + 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 + comedi_data_read takes as argument a + lsampl_t *data which will contain the data + read after the function returns. So in C it is used like this: + + + As lsampl_t is a 32-bit + unsigned int, in Python, the function is used like this: + +rc, data = comedi.comedi_data_read(device, subdevice, channel, range, aref) + + + + 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: comedi.cr_pack, + comedi.cr_range, etc. + So to create and modify a command, one can do in Python: + +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 + + + + 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 cast from the Python object to the + C object. So to create an instruction to call the internal trigger, you would + write in Python: + +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) + + + + When you need to convert from a raw SWIG object to a proxy + object, the .frompointer 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 + .thisown to False. + + + 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 + File object. + You can get a File object via + os.fdopen. For example, to read an array of input data + from a &comedi; device into a numpy array, one could do: + +fileno = comedi.comedi_fileno(device) +file = os.fdopen(fileno, 'r+') +buf = numpy.fromfile(file, dtype=numpy.uint32, count=(nscans * nchans)) + + +
+
diff --git a/doc/reference.xml b/doc/reference.xml index b569d40..b27966e 100644 --- a/doc/reference.xml +++ b/doc/reference.xml @@ -759,5 +759,6 @@ raw/physical conversion functions. +