4. A ComediError exception class. If the underlying comedi
function returns an error indication, the ruby method will raise
- ComediError.
+ ComediError. If the comedi function returns both a status and a
+ value (e.g., comedi_data_read), the status is not returned by the
+ ruby method unless it carries information in addition to indication
+ of failure (e.g., comedi_command_test).
-The file 'demo/cmd' is a straight port of 'cmd.c' from the
-Comedilib 'demo' directory. It illustrates the basics of programming
+5. Ruby booleans. Comedi functions that return C integer boolean values
+ (comedi_range_is_chan_specific, comedi_maxdata_is_chan_specific)
+ have corresponding boolean ruby methods with '?' appended to the
+ method name.
+
+Files in 'demo' are straight ports of their C counterparts from the
+Comedilib 'demo' directory. They illustrate the basics of programming
Comedi commands using Ruby.
-If a Comedilib function returns a value through a pointer passed as an
-input parameter, its Ruby counterpart returns the value as an element
-of an Array.
+For completeness, the set of method definitions invoked by 'comedi.rb'
+is as follows:
+
+ # Module: Comedi
+
+ def open(*args)
+ value = comedi_open(*args)
+ raise ComediError.new if value.nil?
+ return value
+ end
+
+ # Module: Comedi
+
+ def parse_calibration_file(*args)
+ value = comedi_parse_calibration_file(*args)
+ raise ComediError.new if value.nil?
+ return value
+ end
+
+ # Module: Comedi
+
+ def loglevel(*args)
+ value = comedi_loglevel(*args)
+ return value
+ end
+
+ # Module: Comedi
+
+ def perror(*args)
+ value = comedi_perror(*args)
+ return value
+ end
+
+ # Module: Comedi
+
+ def strerrno(*args)
+ value = comedi_strerrno(*args)
+ return value
+ end
+
+ # Module: Comedi
+
+ def errno(*args)
+ value = comedi_errno(*args)
+ return value
+ end
+
+ # Module: Comedi
+
+ def to_phys(*args)
+ value = comedi_to_phys(*args)
+ return value
+ end
+
+ # Module: Comedi
+
+ def from_phys(*args)
+ value = comedi_from_phys(*args)
+ return value
+ end
+
+ # Module: Comedi
+
+ def set_global_oor_behavior(*args)
+ value = comedi_set_global_oor_behavior(*args)
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def close(*args)
+ value = comedi_close(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def fileno(*args)
+ value = comedi_fileno(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_subdevice_type(*args)
+ value = comedi_get_subdevice_type(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def find_subdevice_by_type(*args)
+ value = comedi_find_subdevice_by_type(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_read_subdevice(*args)
+ value = comedi_get_read_subdevice(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_write_device(*args)
+ value = comedi_get_write_device(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_subdevice_flags(*args)
+ value = comedi_get_subdevice_flags(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_n_channels(*args)
+ value = comedi_get_n_channels(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def range_is_chan_specific?(*args)
+ value = comedi_range_is_chan_specific(self, *args)
+ raise ComediError.new if value == -1
+ return ret == 1
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def maxdata_is_chan_specific?(*args)
+ value = comedi_maxdata_is_chan_specific(self, *args)
+ raise ComediError.new if value == -1
+ return ret == 1
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_n_ranges(*args)
+ value = comedi_get_n_ranges(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def find_range(*args)
+ value = comedi_find_range(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_buffer_size(*args)
+ value = comedi_get_buffer_size(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_max_buffer_size(*args)
+ value = comedi_get_max_buffer_size(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def set_buffer_size(*args)
+ value = comedi_set_buffer_size(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def trigger(*args)
+ value = comedi_trigger(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def do_insnlist(*args)
+ value = comedi_do_insnlist(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def do_insn(*args)
+ value = comedi_do_insn(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def lock(*args)
+ value = comedi_lock(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def unlock(*args)
+ value = comedi_unlock(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def data_read_hint(*args)
+ value = comedi_data_read_hint(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def data_write(*args)
+ value = comedi_data_write(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def dio_config(*args)
+ value = comedi_dio_config(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def dio_write(*args)
+ value = comedi_dio_write(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def cancel(*args)
+ value = comedi_cancel(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def command(*args)
+ value = comedi_command(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def poll(*args)
+ value = comedi_poll(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def set_max_buffer_size(*args)
+ value = comedi_set_max_buffer_size(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_buffer_contents(*args)
+ value = comedi_get_buffer_contents(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def mark_buffer_read(*args)
+ value = comedi_mark_buffer_read(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_buffer_offset(*args)
+ value = comedi_get_buffer_offset(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def data_read(*args)
+ status, value = comedi_data_read(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def data_read_delayed(*args)
+ status, value = comedi_data_read_delayed(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def dio_read(*args)
+ status, value = comedi_dio_read(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def dio_bitfield(*args)
+ status, value = comedi_dio_bitfield(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_cmd_src_mask(*args)
+ status, value = comedi_get_cmd_src_mask(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_cmd_generic_timed(*args)
+ status, value = comedi_get_cmd_generic_timed(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def command_test(*args)
+ status, value = comedi_command_test(self, *args)
+ raise ComediError.new if status == -1
+ return status, value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_maxdata(*args)
+ value = comedi_get_maxdata(self, *args)
+ raise ComediError.new if value == 0
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def apply_calibration(*args)
+ value = comedi_apply_calibration(self, *args)
+ raise ComediError.new if value < 0
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def apply_parsed_calibration(*args)
+ value = comedi_apply_parsed_calibration(self, *args)
+ raise ComediError.new if value < 0
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_driver_name(*args)
+ value = comedi_get_driver_name(self, *args)
+ raise ComediError.new if value.nil?
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_board_name(*args)
+ value = comedi_get_board_name(self, *args)
+ raise ComediError.new if value.nil?
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_range(*args)
+ value = comedi_get_range(self, *args)
+ raise ComediError.new if value.nil?
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_default_calibration_path(*args)
+ value = comedi_get_default_calibration_path(self, *args)
+ raise ComediError.new if value.nil?
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_n_subdevices(*args)
+ value = comedi_get_n_subdevices(self, *args)
+ return value
+ end
+
+ # Module: SWIG::TYPE_p_comedi_t
+
+ def get_version_code(*args)
+ value = comedi_get_version_code(self, *args)
+ return value
+ end
+
+ # Module: Comedi::Comedi_sv_t
+
+ def sv_init(*args)
+ value = comedi_sv_init(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: Comedi::Comedi_sv_t
+
+ def sv_update(*args)
+ value = comedi_sv_update(self, *args)
+ raise ComediError.new if value == -1
+ return value
+ end
+
+ # Module: Comedi::Comedi_sv_t
- ret, cmd = dev.command_test(cmd)
+ def sv_measure(*args)
+ status, value = comedi_sv_measure(self, *args)
+ raise ComediError.new if status == -1
+ return value
+ end
-Because the command object is used by command_test() it appears as an
-input parameter as well. If the pointer is used only for output, it is
-omitted from the parameter list. For example:
+ # Module: Comedi::Comedi_calibration_t
- data = dev.data_read(subdevice, channel, range, aref);
+ def cleanup_calibration_file(*args)
+ value = comedi_cleanup_calibration_file(self, *args)
+ return value
+ end
Steven Jenkins
steven.jenkins@ieee.org
# This file is syntactic sugar for accessing the Ruby comedilib
# extension library generated by SWIG. The syntactic sugar is in
-# four forms:
+# several forms:
#
# (1) Method names without the 'comedi_' prefix. The Comedi module
# disambiguates the namespace.
#
# (4) A ComediError exception class. If the underlying comedi
# function returns an error indication, the ruby method will raise
-# ComediError.
+# ComediError. If the comedi function returns both a status and a
+# value (e.g., comedi_data_read), the status is not returned by the
+# ruby method unless it carries information in addition to indication
+# of failure (e.g., comedi_command_test).
+#
+# (5) Ruby booleans. Comedi functions that return C integer boolean values
+# (comedi_range_is_chan_specific, comedi_maxdata_is_chan_specific) have
+# corresponding boolean ruby methods with '?' appended to the method name.
require 'comedi.so'
# wrap_method is the basis for wrap_module_method and
# wrap_instance_method.
- def wrap_method(mod, name, err, arglist)
- wrap_def = %Q{
- def #{name}(*args)
- ret = comedi_#{name}(#{arglist})
- }
+ def wrap_method(mod, name, err, multi, arglist)
+
+ cname = name
+ ret = 'value'
+ status = 'value'
+ value = 'value'
+
+ # If name ends in '?', make ruby wrapper a boolean.
+
+ if bool = (name =~ /\?$/)
+ value = 'ret == 1'
+ cname = name.sub(/\?$/, '')
+ elsif multi == :simple
+ ret = 'status, value'
+ status = 'status'
+ value = 'value'
+ elsif multi == :compound
+ ret = 'status, value'
+ status = 'status'
+ value = 'status, value'
+ end
+
+ wrap_def = %Q{# Module: #{mod}\n\n}
+ wrap_def << %Q{def #{name}(*args)\n}
+ wrap_def << %Q{ #{ret} = comedi_#{cname}(#{arglist})\n}
+
+ # Raise exceptions if required.
+
unless err == :none
- wrap_def << %Q{ raise ComediError.new if }
+ wrap_def << %Q{ raise ComediError.new if }
case err
when :neg
- wrap_def << %Q{ ret < 0 }
+ wrap_def << %Q{#{status} < 0\n}
when nil
- wrap_def << %Q{ ret.nil? }
+ wrap_def << %Q{#{status}.nil?\n}
else
- wrap_def << %Q{ ret == #{err} }
+ wrap_def << %Q{#{status} == #{err}\n}
end
end
- wrap_def << %Q{
- ret
- end
- }
+
+ # Return value.
+
+ wrap_def << %Q{ return #{value}\n}
+ wrap_def << %Q{end\n\n}
+
+ # Execute definition.
+
+ puts wrap_def if __FILE__ == 'comedi.rb'
mod.module_eval wrap_def
end
# unnecessary comedi_ prefix. The wrapped method raises
# ComediError if the return value equals a specified value.
- def wrap_module_method(mod, name, err)
- wrap_method(mod, name, err, '*args')
+ def wrap_module_method(mod, name, err, multi)
+ wrap_method(mod, name, err, multi, '*args')
end
# wrap_instance_method defines instance methods for any of several
# explicit receiver. The wrapped method raises ComediError
# if the return value equals a specified value.
- def wrap_instance_method(mod, name, err)
- wrap_method(mod, name, err, 'self, *args')
+ def wrap_instance_method(mod, name, err, multi)
+ wrap_method(mod, name, err, multi, 'self, *args')
end
- # This struct holds information for methods with return class and
- # error indication.
+ # This struct holds information for methods with return class,
+ # error, and multi-return indication.
+
+ Method_group = Struct.new(:class, :err, :multi, :names)
- Method_group = Struct.new(:class, :err, :names)
+ # Define method groups.
- # Wrap Comedi module methods
+ module_methods = [
- [
# Comedi module methods that return nil on error.
- Method_group.new(Comedi, nil, %w{
+ Method_group.new(Comedi, nil, nil, %w{
open
parse_calibration_file
}),
# Comedi module methods that do not indicate errors.
- Method_group.new(Comedi, :none, %w{
+ Method_group.new(Comedi, :none, nil, %w{
loglevel
perror
strerrno
from_phys
set_global_oor_behavior
}),
- ].each do |d|
- d.names.each do |n|
- wrap_module_method(d.class, n, d.err)
- end
- end
-
- # Wrap Instance methods
+ ]
+
+ instance_methods = [
- [
# SWIG::TYPE_p_comedi_t methods that return -1 on error.
- Method_group.new(SWIG::TYPE_p_comedi_t, -1, %w{
+ Method_group.new(SWIG::TYPE_p_comedi_t, -1, nil, %w{
close
fileno
get_subdevice_type
get_write_device
get_subdevice_flags
get_n_channels
- range_is_chan_specific
- maxdata_is_chan_specific
+ range_is_chan_specific?
+ maxdata_is_chan_specific?
get_n_ranges
find_range
get_buffer_size
do_insn
lock
unlock
- data_read
- data_read_delayed
+ data_read_hint
data_write
dio_config
- dio_read
dio_write
- dio_bitfield
- get_cmd_src_mask
- get_cmd_generic_timed
cancel
command
- command_test
poll
set_max_buffer_size
get_buffer_contents
get_buffer_offset
}),
+ # SWIG::TYPE_p_comedi_t methods that return status and a
+ # value. Status is -1 on error. Status is discarded.
+
+ Method_group.new(SWIG::TYPE_p_comedi_t, -1, :simple, %w{
+ data_read
+ data_read_delayed
+ dio_read
+ dio_bitfield
+ get_cmd_src_mask
+ get_cmd_generic_timed
+ }),
+
+ # SWIG::TYPE_p_comedi_t methods that return status and a
+ # value. Status is -1 on error. Status and value are both
+ # returned.
+
+ Method_group.new(SWIG::TYPE_p_comedi_t, -1, :compound, %w{
+ command_test
+ }),
+
# SWIG::TYPE_p_comedi_t methods that return 0 on error.
- Method_group.new(SWIG::TYPE_p_comedi_t, 0, %w{
+ Method_group.new(SWIG::TYPE_p_comedi_t, 0, nil, %w{
get_maxdata
}),
# SWIG::TYPE_p_comedi_t methods that return <0 on error.
- Method_group.new(SWIG::TYPE_p_comedi_t, :neg, %w{
+ Method_group.new(SWIG::TYPE_p_comedi_t, :neg, nil, %w{
apply_calibration
apply_parsed_calibration
}),
# SWIG::TYPE_p_comedi_t methods that return nil on error.
- Method_group.new(SWIG::TYPE_p_comedi_t, nil, %w{
+ Method_group.new(SWIG::TYPE_p_comedi_t, nil, nil, %w{
get_driver_name
get_board_name
get_range
# SWIG::TYPE_p_comedi_t methods that do not indicate errors.
- Method_group.new(SWIG::TYPE_p_comedi_t, :none, %w{
+ Method_group.new(SWIG::TYPE_p_comedi_t, :none, nil, %w{
get_n_subdevices
get_version_code
- data_read_hint
}),
- # Comedi_sv_t methods that return -1 on errors.
+ # Comedi_sv_t methods that return -1 on error.
- Method_group.new(Comedi_sv_t, -1, %w{
+ Method_group.new(Comedi_sv_t, -1, nil, %w{
sv_init
sv_update
+ }),
+
+ # Comedi_sv_t methods that return status and a value. Status
+ # is -1 on error.
+
+ Method_group.new(Comedi_sv_t, -1, :simple, %w{
sv_measure
}),
# Comedi_calibration_t methods that do not indicate errors.
- Method_group.new(Comedi_calibration_t, :none, %w{
+ Method_group.new(Comedi_calibration_t, :none, nil, %w{
cleanup_calibration_file
})
- ].each do |d|
+ ]
+
+ # Wrap Comedi module methods.
+
+ module_methods.each do |d|
+ d.names.each do |n|
+ wrap_module_method(d.class, n, d.err, d.multi)
+ end
+ end
+
+ # Wrap instance methods.
+
+ instance_methods.each do |d|
d.names.each do |n|
- wrap_instance_method(d.class, n, d.err)
+ wrap_instance_method(d.class, n, d.err, d.multi)
end
end
end