robobuilder 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (7) hide show
  1. data/.document +1 -0
  2. data/COPYING +680 -0
  3. data/README.md +44 -0
  4. data/Rakefile +176 -0
  5. data/ext/robobuilder.cc +341 -0
  6. data/lib/robobuilder_ext.rb +378 -0
  7. metadata +70 -0
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ robobuilder
2
+ ======
3
+
4
+ **Author**: Jan Wedekind
5
+ **Copyright**: 2011
6
+ **License**: GPL
7
+
8
+ Synopsis
9
+ --------
10
+
11
+ This Ruby extension defines the class {Robobuilder} for communicating with a Robobuilder robot via serial port or Bluetooth serial.
12
+
13
+ Installation
14
+ ------------
15
+
16
+ To install this Ruby extension, use the following command:
17
+
18
+ $ sudo gem install robobuilder
19
+
20
+ Alternatively you can build and install the Ruby extension from source as follows:
21
+
22
+ $ rake
23
+ $ sudo rake install
24
+
25
+ Usage
26
+ -----
27
+
28
+ Simply run Interactive Ruby:
29
+
30
+ $ irb
31
+
32
+ You can load the Ruby extension like this:
33
+
34
+ require 'rubygems'
35
+ require 'robobuilder'
36
+
37
+ See documentation of {Robobuilder} on how to use this Ruby extension.
38
+
39
+ External Links
40
+ --------------
41
+
42
+ * [Robobuilder](http://www.robobuilder.net/eng/)
43
+ * [Page at Robosavvy](http://robosavvy.com/site/index.php?task=view&Itemid=128)
44
+
data/Rakefile ADDED
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env ruby
2
+ require 'date'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/loaders/makefile'
7
+ require 'rbconfig'
8
+
9
+ PKG_NAME = 'robobuilder'
10
+ PKG_VERSION = '0.3.0'
11
+ CFG = RbConfig::CONFIG
12
+ CXX = ENV[ 'CXX' ] || 'g++'
13
+ RB_FILES = FileList[ 'lib/**/*.rb' ]
14
+ CC_FILES = FileList[ 'ext/*.cc' ]
15
+ HH_FILES = FileList[ 'ext/*.hh' ] + FileList[ 'ext/*.tcc' ]
16
+ TC_FILES = FileList[ 'test/tc_*.rb' ]
17
+ TS_FILES = FileList[ 'test/ts_*.rb' ]
18
+ SO_FILE = "ext/#{PKG_NAME.tr '\-', '_'}.#{CFG[ 'DLEXT' ]}"
19
+ PKG_FILES = [ 'Rakefile', 'README.md', 'COPYING', '.document' ] +
20
+ RB_FILES + CC_FILES + HH_FILES + TS_FILES + TC_FILES
21
+ BIN_FILES = [ 'README.md', 'COPYING', '.document', SO_FILE ] +
22
+ RB_FILES + TS_FILES + TC_FILES
23
+ SUMMARY = %q{Ruby extension for controlling a Robobuilder}
24
+ DESCRIPTION = %q{This Ruby extension defines the Robobuilder class for communicating a Robobuilder via the serial port or a Bluetooth serial connection.}
25
+ AUTHOR = %q{Jan Wedekind}
26
+ EMAIL = %q{jan@wedesoft.de}
27
+ HOMEPAGE = %q{http://wedesoft.github.com/robobuilder/}
28
+
29
+ OBJ = CC_FILES.ext 'o'
30
+ $CXXFLAGS = "-DNDEBUG #{CFG[ 'CPPFLAGS' ]} #{CFG[ 'CFLAGS' ]}"
31
+ if CFG[ 'rubyhdrdir' ]
32
+ $CXXFLAGS = "#{$CXXFLAGS} -I#{CFG[ 'rubyhdrdir' ]} " +
33
+ "-I#{CFG[ 'rubyhdrdir' ]}/#{CFG[ 'arch' ]}"
34
+ else
35
+ $CXXFLAGS = "#{$CXXFLAGS} -I#{CFG[ 'archdir' ]}"
36
+ end
37
+ $LIBRUBYARG = "-L#{CFG[ 'libdir' ]} #{CFG[ 'LIBRUBYARG' ]} #{CFG[ 'LDFLAGS' ]} " +
38
+ "#{CFG[ 'SOLIBS' ]} #{CFG[ 'DLDLIBS' ]}"
39
+ $SITELIBDIR = CFG[ 'sitelibdir' ]
40
+ $SITEARCHDIR = CFG[ 'sitearchdir' ]
41
+ $LDSHARED = CFG[ 'LDSHARED' ][ CFG[ 'LDSHARED' ].index( ' ' ) .. -1 ]
42
+
43
+ task :default => :all
44
+
45
+ desc 'Compile Ruby extension (default)'
46
+ task :all => [ SO_FILE ]
47
+
48
+ file SO_FILE => OBJ do |t|
49
+ sh "#{CXX} #{$LDSHARED} -o #{t.name} #{OBJ} #{$LIBRUBYARG}"
50
+ end
51
+
52
+ task :test => [ SO_FILE ]
53
+
54
+ desc 'Install Ruby extension'
55
+ task :install => :all do
56
+ verbose true do
57
+ for f in RB_FILES do
58
+ FileUtils.mkdir_p "#{$SITELIBDIR}/#{File.dirname f.gsub( /^lib\//, '' )}"
59
+ FileUtils.cp_r f, "#{$SITELIBDIR}/#{f.gsub( /^lib\//, '' )}"
60
+ end
61
+ FileUtils.mkdir_p $SITEARCHDIR
62
+ FileUtils.cp SO_FILE, "#{$SITEARCHDIR}/#{File.basename SO_FILE}"
63
+ end
64
+ end
65
+
66
+ desc 'Uninstall Ruby extension'
67
+ task :uninstall do
68
+ verbose true do
69
+ for f in RB_FILES do
70
+ FileUtils.rm_f "#{$SITELIBDIR}/#{f.gsub /^lib\//, ''}"
71
+ end
72
+ FileUtils.rm_f "#{$SITEARCHDIR}/#{File.basename SO_FILE}"
73
+ end
74
+ end
75
+
76
+ Rake::TestTask.new do |t|
77
+ t.libs << 'ext'
78
+ t.test_files = TC_FILES
79
+ end
80
+
81
+ begin
82
+ require 'yard'
83
+ YARD::Rake::YardocTask.new :yard do |y|
84
+ y.files << RB_FILES
85
+ end
86
+ rescue LoadError
87
+ STDERR.puts 'Please install \'yard\' if you want to generate documentation'
88
+ end
89
+
90
+ Rake::PackageTask.new PKG_NAME, PKG_VERSION do |p|
91
+ p.need_tar = true
92
+ p.package_files = PKG_FILES
93
+ end
94
+
95
+ begin
96
+ require 'rubygems'
97
+ require 'rubygems/builder'
98
+ $SPEC = Gem::Specification.new do |s|
99
+ s.name = PKG_NAME
100
+ s.version = PKG_VERSION
101
+ s.platform = Gem::Platform::RUBY
102
+ s.date = Date.today.to_s
103
+ s.summary = SUMMARY
104
+ s.description = DESCRIPTION
105
+ s.author = AUTHOR
106
+ s.email = EMAIL
107
+ s.homepage = HOMEPAGE
108
+ s.files = PKG_FILES
109
+ s.test_files = TC_FILES
110
+ s.require_paths = [ 'lib', 'ext' ]
111
+ # s.rubyforge_project = %q{}
112
+ s.extensions = %w{Rakefile}
113
+ s.has_rdoc = 'yard'
114
+ s.extra_rdoc_files = []
115
+ s.add_development_dependency %q{rake}
116
+ end
117
+ GEM_SOURCE = "#{PKG_NAME}-#{PKG_VERSION}.gem"
118
+ $BINSPEC = Gem::Specification.new do |s|
119
+ s.name = PKG_NAME
120
+ s.version = PKG_VERSION
121
+ s.platform = Gem::Platform::CURRENT
122
+ s.date = Date.today.to_s
123
+ s.summary = SUMMARY
124
+ s.description = DESCRIPTION
125
+ s.author = AUTHOR
126
+ s.email = EMAIL
127
+ s.homepage = HOMEPAGE
128
+ s.files = BIN_FILES
129
+ s.test_files = TC_FILES
130
+ s.require_paths = [ 'lib', 'ext' ]
131
+ # s.rubyforge_project = %q{}
132
+ s.has_rdoc = 'yard'
133
+ s.extra_rdoc_files = []
134
+ end
135
+ GEM_BINARY = "#{PKG_NAME}-#{PKG_VERSION}-#{$BINSPEC.platform}.gem"
136
+ desc "Build the gem file #{GEM_SOURCE}"
137
+ task :gem => [ "pkg/#{GEM_SOURCE}" ]
138
+ file "pkg/#{GEM_SOURCE}" => [ 'pkg' ] + $SPEC.files do
139
+ when_writing 'Creating GEM' do
140
+ Gem::Builder.new( $SPEC ).build
141
+ verbose true do
142
+ FileUtils.mv GEM_SOURCE, "pkg/#{GEM_SOURCE}"
143
+ end
144
+ end
145
+ end
146
+ desc "Build the gem file #{GEM_BINARY}"
147
+ task :gem_binary => [ "pkg/#{GEM_BINARY}" ]
148
+ file "pkg/#{GEM_BINARY}" => [ 'pkg' ] + $BINSPEC.files do
149
+ when_writing 'Creating binary GEM' do
150
+ Gem::Builder.new( $BINSPEC ).build
151
+ verbose true do
152
+ FileUtils.mv GEM_BINARY, "pkg/#{GEM_BINARY}"
153
+ end
154
+ end
155
+ end
156
+ rescue LoadError
157
+ STDERR.puts 'Please install \'rubygems\' if you want to create Gem packages'
158
+ end
159
+
160
+ rule '.o' => '.cc' do |t|
161
+ sh "#{CXX} #{$CXXFLAGS} -c -o #{t.name} #{t.source}"
162
+ end
163
+
164
+ file ".depends.mf" do |t|
165
+ sh "g++ -MM #{CC_FILES.join ' '} | " +
166
+ "sed -e :a -e N -e 's/\\n/\\$/g' -e ta | " +
167
+ "sed -e 's/ *\\\\\\$ */ /g' -e 's/\\$/\\n/g' | sed -e 's/^/ext\\//' > #{t.name}"
168
+ end
169
+ CC_FILES.each do |t|
170
+ file t.ext(".o") => t
171
+ end
172
+ import ".depends.mf"
173
+
174
+ CLEAN.include 'ext/*.o'
175
+ CLOBBER.include SO_FILE, 'doc', '.yardoc', '.depends.mf'
176
+
@@ -0,0 +1,341 @@
1
+ /* Robobuilder - Ruby-extension to control Robobuilder
2
+ Copyright (C) 2009 Jan Wedekind
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
+ #ifndef NDEBUG
17
+ #include <iostream>
18
+ #endif
19
+ #include <boost/shared_array.hpp>
20
+ #include <boost/smart_ptr.hpp>
21
+ #include <ruby.h>
22
+ #include <errno.h>
23
+ #include <sys/stat.h>
24
+ #include <sys/types.h>
25
+ #include <termios.h>
26
+ #include <fcntl.h>
27
+ #include <string>
28
+ #include <sstream>
29
+
30
+ class Error: public std::exception
31
+ {
32
+ public:
33
+ Error(void) {}
34
+ Error( Error &e ): std::exception( e )
35
+ { m_message << e.m_message.str(); }
36
+ virtual ~Error(void) throw() {}
37
+ template< typename T >
38
+ std::ostream &operator<<( const T &t )
39
+ { m_message << t; return m_message; }
40
+ std::ostream &operator<<( std::ostream& (*__pf)( std::ostream&) )
41
+ { (*__pf)( m_message ); return m_message; }
42
+ virtual const char* what(void) const throw() {
43
+ temp = m_message.str();
44
+ return temp.c_str();
45
+ return NULL;
46
+ }
47
+ protected:
48
+ std::ostringstream m_message;
49
+ static std::string temp;
50
+ };
51
+
52
+ class Robobuilder
53
+ {
54
+ public:
55
+ Robobuilder( const std::string &device = "/dev/ttyS0" ) throw (Error);
56
+ virtual ~Robobuilder(void);
57
+ std::string inspect(void) const;
58
+ void close(void);
59
+ int write( const char *data, int length ) throw (Error);
60
+ std::string read( int num ) throw (Error);
61
+ void flush(void) throw (Error);
62
+ int timeout(void);
63
+ void setTimeout( int value ) throw (Error);
64
+ static VALUE cRubyClass;
65
+ static VALUE registerRubyClass(void);
66
+ static void deleteRubyObject( void *ptr );
67
+ static VALUE wrapNew( VALUE rbClass, VALUE rbDevice );
68
+ static VALUE wrapInspect( VALUE rbSelf );
69
+ static VALUE wrapClose( VALUE rbSelf );
70
+ static VALUE wrapWrite( VALUE rbSelf, VALUE rbData );
71
+ static VALUE wrapRead( VALUE rbSelf, VALUE rbNum );
72
+ static VALUE wrapFlush( VALUE rbSelf );
73
+ static VALUE wrapTimeout( VALUE rbSelf );
74
+ static VALUE wrapSetTimeout( VALUE rbSelf, VALUE rbValue );
75
+ protected:
76
+ std::string m_device;
77
+ int m_fd;
78
+ struct termios m_tio;
79
+ };
80
+
81
+ typedef boost::shared_ptr< Robobuilder > RobobuilderPtr;
82
+
83
+ using namespace boost;
84
+ using namespace std;
85
+
86
+ string Error::temp;
87
+
88
+ #define ERRORMACRO( condition, class, params, message ) \
89
+ if ( !( condition ) ) { \
90
+ class _e params; \
91
+ _e << message; \
92
+ throw _e; \
93
+ };
94
+
95
+ VALUE Robobuilder::cRubyClass = Qnil;
96
+
97
+ #undef SW_FLOW_CONTROL
98
+ #undef HW_FLOW_CONTROL
99
+
100
+ Robobuilder::Robobuilder( const string &device ) throw (Error):
101
+ m_device(device), m_fd(-1)
102
+ {
103
+ try {
104
+ m_fd = open( device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
105
+ ERRORMACRO( m_fd != -1, Error, ,
106
+ "Error opening serial port: " << strerror( errno ) );
107
+ int flags = fcntl( m_fd, F_GETFL, 0 );
108
+ ERRORMACRO( fcntl( m_fd, F_SETFL, flags | O_NONBLOCK ) != -1, Error, ,
109
+ "Error switching to non-blocking mode: "
110
+ << strerror( errno ) );
111
+ tcflush( m_fd, TCIOFLUSH );
112
+ bzero( &m_tio, sizeof( m_tio ) );
113
+ #ifdef SW_FLOW_CONTROL
114
+ m_tio.c_iflag = IXON |IXOFF;
115
+ #else
116
+ m_tio.c_iflag = 0;
117
+ #endif
118
+ m_tio.c_oflag = 0;
119
+ m_tio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
120
+ #ifdef HW_FLOW_CONTROL
121
+ m_tio.c_cflag |= CRTSCTS;
122
+ #endif
123
+ m_tio.c_lflag = 0;
124
+ #ifdef SW_FLOW_CONTROL
125
+ m_tio.c_cc[ VSTART ] = 0x11;
126
+ m_tio.c_cc[ VSTOP ] = 0x13;
127
+ #endif
128
+ #ifdef HW_FLOW_CONTROL
129
+ m_tio.c_cc[ VSTART ] = _POSIX_VDISABLE;
130
+ m_tio.c_cc[ VSTOP ] = _POSIX_VDISABLE;
131
+ #endif
132
+ m_tio.c_cc[ VTIME ] = 1;// * 1/10 second
133
+ m_tio.c_cc[ VMIN ] = 0;// bytes
134
+ ERRORMACRO( tcsetattr( m_fd, TCSANOW, &m_tio ) != -1, Error, ,
135
+ "Error configuring serial port: " << strerror( errno ) );
136
+ ERRORMACRO( fcntl( m_fd, F_SETFL, flags & ~O_NONBLOCK ) != -1, Error, ,
137
+ "Error switching to blocking mode" );
138
+ } catch ( Error &e ) {
139
+ close();
140
+ throw e;
141
+ };
142
+ }
143
+
144
+ Robobuilder::~Robobuilder(void)
145
+ {
146
+ close();
147
+ }
148
+
149
+ string Robobuilder::inspect(void) const
150
+ {
151
+ ostringstream s;
152
+ s << "Robobuilder( \"" << m_device << "\" )";
153
+ return s.str();
154
+ }
155
+
156
+ void Robobuilder::close(void)
157
+ {
158
+ if ( m_fd != -1 ) {
159
+ ::close( m_fd );
160
+ m_fd = -1;
161
+ };
162
+ }
163
+
164
+ int Robobuilder::write( const char *data, int length ) throw (Error)
165
+ {
166
+ ERRORMACRO( m_fd != -1, Error, , "Serial connection is closed" );
167
+ int n = ::write( m_fd, data, length );
168
+ ERRORMACRO( n != -1, Error, , "Error writing to serial device: "
169
+ << strerror( errno ) );
170
+ return n;
171
+ }
172
+
173
+ void Robobuilder::flush(void) throw (Error)
174
+ {
175
+ ERRORMACRO( m_fd != -1, Error, , "Serial connection is closed" );
176
+ ERRORMACRO( tcflush( m_fd, TCIOFLUSH ) != -1, Error, ,
177
+ "Error flushing serial I/O: "
178
+ << strerror( errno ) );
179
+ }
180
+
181
+ int Robobuilder::timeout(void)
182
+ {
183
+ ERRORMACRO( m_fd != -1, Error, , "Serial connection is closed" );
184
+ int retVal;
185
+ if ( m_tio.c_cc[ VMIN ] == 0 )
186
+ retVal = m_tio.c_cc[ VTIME ];
187
+ else
188
+ retVal = INT_MAX;
189
+ return retVal;
190
+ }
191
+
192
+ void Robobuilder::setTimeout( int value ) throw (Error)
193
+ {
194
+ ERRORMACRO( m_fd != -1, Error, , "Serial connection is closed" );
195
+ if ( value == INT_MAX ) {
196
+ m_tio.c_cc[ VMIN ] = 1;
197
+ m_tio.c_cc[ VTIME ] = 0;
198
+ } else {
199
+ m_tio.c_cc[ VMIN ] = 0;
200
+ m_tio.c_cc[ VTIME ] = value;
201
+ };
202
+ ERRORMACRO( tcsetattr( m_fd, TCSANOW, &m_tio ) != -1, Error, ,
203
+ "Error configuring serial port: " << strerror( errno ) );
204
+ }
205
+
206
+ std::string Robobuilder::read( int num ) throw (Error)
207
+ {
208
+ ERRORMACRO( m_fd != -1, Error, , "Serial connection is closed" );
209
+ shared_array< char > buffer( new char[ num ] );
210
+ int n = ::read( m_fd, buffer.get(), num );
211
+ ERRORMACRO( n != -1, Error, , "Error reading from serial device: "
212
+ << strerror( errno ) );
213
+ return string( buffer.get(), n );
214
+ }
215
+
216
+ VALUE Robobuilder::registerRubyClass(void)
217
+ {
218
+ cRubyClass = rb_define_class( "Robobuilder", rb_cObject );
219
+ rb_define_const( cRubyClass, "INFINITE", INT2NUM(INT_MAX) );
220
+ rb_define_singleton_method( cRubyClass, "new",
221
+ RUBY_METHOD_FUNC( wrapNew ), 1 );
222
+ rb_define_method( cRubyClass, "inspect",
223
+ RUBY_METHOD_FUNC( wrapInspect ), 0 );
224
+ rb_define_method( cRubyClass, "close",
225
+ RUBY_METHOD_FUNC( wrapClose ), 0 );
226
+ rb_define_method( cRubyClass, "write",
227
+ RUBY_METHOD_FUNC( wrapWrite ), 1 );
228
+ rb_define_method( cRubyClass, "read",
229
+ RUBY_METHOD_FUNC( wrapRead ), 1 );
230
+ rb_define_method( cRubyClass, "flush",
231
+ RUBY_METHOD_FUNC( wrapFlush ), 0 );
232
+ rb_define_method( cRubyClass, "timeout",
233
+ RUBY_METHOD_FUNC( wrapTimeout ), 0 );
234
+ rb_define_method( cRubyClass, "timeout=",
235
+ RUBY_METHOD_FUNC( wrapSetTimeout ), 1 );
236
+ return cRubyClass;
237
+ }
238
+
239
+ void Robobuilder::deleteRubyObject( void *ptr )
240
+ {
241
+ delete (RobobuilderPtr *)ptr;
242
+ }
243
+
244
+
245
+ VALUE Robobuilder::wrapNew( VALUE rbClass, VALUE rbDevice )
246
+ {
247
+ VALUE retVal = Qnil;
248
+ try {
249
+ rb_check_type( rbDevice, T_STRING );
250
+ RobobuilderPtr ptr( new Robobuilder( StringValuePtr( rbDevice ) ) );
251
+ retVal = Data_Wrap_Struct( rbClass, 0, deleteRubyObject,
252
+ new RobobuilderPtr( ptr ) );
253
+ } catch ( std::exception &e ) {
254
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
255
+ };
256
+ return retVal;
257
+ }
258
+
259
+ VALUE Robobuilder::wrapInspect( VALUE rbSelf )
260
+ {
261
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
262
+ string retVal( (*self)->inspect() );
263
+ return rb_str_new( retVal.c_str(), retVal.length() );
264
+ }
265
+
266
+ VALUE Robobuilder::wrapClose( VALUE rbSelf )
267
+ {
268
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
269
+ (*self)->close();
270
+ return rbSelf;
271
+ }
272
+
273
+ VALUE Robobuilder::wrapWrite( VALUE rbSelf, VALUE rbData )
274
+ {
275
+ VALUE rbRetVal = Qnil;
276
+ try {
277
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
278
+ rbRetVal = INT2NUM( (*self)->write( StringValuePtr( rbData ),
279
+ RSTRING_LEN( rbData ) ) );
280
+ } catch ( std::exception &e ) {
281
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
282
+ };
283
+ return rbRetVal;
284
+ }
285
+
286
+ VALUE Robobuilder::wrapRead( VALUE rbSelf, VALUE rbNum )
287
+ {
288
+ VALUE rbRetVal = Qnil;
289
+ try {
290
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
291
+ string retVal( (*self)->read( NUM2INT( rbNum ) ) );
292
+ rbRetVal = rb_str_new( retVal.c_str(), retVal.length() );
293
+ } catch ( std::exception &e ) {
294
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
295
+ };
296
+ return rbRetVal;
297
+ }
298
+
299
+ VALUE Robobuilder::wrapFlush( VALUE rbSelf )
300
+ {
301
+ try {
302
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
303
+ (*self)->flush();
304
+ } catch ( std::exception &e ) {
305
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
306
+ };
307
+ return Qnil;
308
+ }
309
+
310
+ VALUE Robobuilder::wrapTimeout( VALUE rbSelf )
311
+ {
312
+ VALUE rbRetVal = Qnil;
313
+ try {
314
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
315
+ rbRetVal = INT2NUM( (*self)->timeout() );
316
+ } catch ( std::exception &e ) {
317
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
318
+ };
319
+ return rbRetVal;
320
+ }
321
+
322
+ VALUE Robobuilder::wrapSetTimeout( VALUE rbSelf, VALUE rbValue )
323
+ {
324
+ try {
325
+ RobobuilderPtr *self; Data_Get_Struct( rbSelf, RobobuilderPtr, self );
326
+ (*self)->setTimeout( NUM2INT( rbValue ) );
327
+ } catch ( std::exception &e ) {
328
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
329
+ };
330
+ return rbValue;
331
+ }
332
+
333
+ extern "C" {
334
+
335
+ void Init_robobuilder(void)
336
+ {
337
+ Robobuilder::registerRubyClass();
338
+ rb_require( "robobuilder_ext.rb" );
339
+ }
340
+
341
+ }