rsruby 0.4.0 → 0.4.2

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.
@@ -253,6 +253,8 @@ VALUE to_ruby_with_mode(SEXP robj, int mode)
253
253
  VALUE obj;
254
254
  int i;
255
255
 
256
+ int old_mode = mode;
257
+
256
258
  switch (mode)
257
259
  {
258
260
  case PROC_CONVERSION:
@@ -275,6 +277,7 @@ VALUE to_ruby_with_mode(SEXP robj, int mode)
275
277
  obj = Data_Wrap_Struct(rb_const_get(rb_cObject,
276
278
  rb_intern("RObj")), 0, 0, robj);
277
279
  rb_iv_set(obj,"@conversion",INT2FIX(TOP_MODE));
280
+ rb_iv_set(obj,"@wrap",Qfalse);
278
281
  }
279
282
 
280
283
  return obj;
@@ -424,7 +427,8 @@ int
424
427
  from_proc_table(SEXP robj, VALUE *fun)
425
428
  {
426
429
  VALUE proc_table, procs, proc, funs, res, obj, mode;
427
- int i, l, error;
430
+ VALUE args[2];
431
+ int i, l, error, exception;
428
432
 
429
433
  proc_table = rb_cvar_get(rb_const_get(rb_cObject,
430
434
  rb_intern("RSRuby")),
@@ -444,13 +448,12 @@ from_proc_table(SEXP robj, VALUE *fun)
444
448
  obj = Data_Wrap_Struct(rb_const_get(rb_cObject,
445
449
  rb_intern("RObj")), 0, 0, robj);
446
450
  rb_iv_set(obj,"@conversion",INT2FIX(TOP_MODE));
451
+ rb_iv_set(obj,"@wrap",Qfalse);
447
452
 
448
453
  error = 0;
449
454
  for (i=0; i<l; i++) {
450
455
  proc = rb_ary_entry(procs, i);
451
456
 
452
- //TODO - something strange here in RPy isn't there infinite
453
- //recursion?? We set to basic mode in function to avoid.
454
457
  mode = rb_cvar_get(rb_const_get(rb_cObject,
455
458
  rb_intern("RSRuby")),
456
459
  rb_intern("@@default_mode"));
@@ -459,19 +462,11 @@ from_proc_table(SEXP robj, VALUE *fun)
459
462
  rb_intern("@@default_mode"),
460
463
  INT2FIX(BASIC_CONVERSION),Qtrue);
461
464
 
462
- //Call function
463
- res = rb_funcall(proc, rb_intern("call"), 1, obj);
464
-
465
- //Reset mode
466
- rb_cvar_set(rb_const_get(rb_cObject,
467
- rb_intern("RSRuby")),
468
- rb_intern("@@default_mode"),
469
- mode,Qtrue);
465
+ //New safe code
466
+ args[0] = proc;
467
+ args[1] = obj;
468
+ res = rb_ensure(call_proc,(VALUE) &args[0],reset_mode,mode);
470
469
 
471
- if (!res) {
472
- error = -1;
473
- break;
474
- }
475
470
  if (RTEST(res)) {
476
471
  *fun = rb_ary_entry(funs, i);
477
472
  break;
@@ -481,10 +476,27 @@ from_proc_table(SEXP robj, VALUE *fun)
481
476
  return error;
482
477
  }
483
478
 
479
+ VALUE call_proc(VALUE data){
480
+ VALUE *args = (VALUE *) data;
481
+ return rb_funcall(args[0], rb_intern("call"), 1, args[1]);
482
+ }
483
+
484
+ VALUE reset_mode(VALUE mode){
485
+
486
+ rb_cvar_set(rb_const_get(rb_cObject,
487
+ rb_intern("RSRuby")),
488
+ rb_intern("@@default_mode"),
489
+ mode,Qtrue);
490
+
491
+ return Qnil;
492
+
493
+ }
494
+
484
495
  int
485
496
  to_ruby_proc(SEXP robj, VALUE *obj)
486
497
  {
487
498
  VALUE fun=Qnil, tmp, mode;
499
+ VALUE args[2];
488
500
  int i;
489
501
 
490
502
  //Find function from proc table. integer is returned
@@ -503,6 +515,7 @@ to_ruby_proc(SEXP robj, VALUE *obj)
503
515
  tmp = Data_Wrap_Struct(rb_const_get(rb_cObject,
504
516
  rb_intern("RObj")), 0, 0, robj);
505
517
  rb_iv_set(tmp,"@conversion",INT2FIX(TOP_MODE));
518
+ rb_iv_set(tmp,"@wrap",Qfalse);
506
519
 
507
520
  //Again set conversion mode to basic to prevent recursion
508
521
  mode = rb_cvar_get(rb_const_get(rb_cObject,
@@ -513,14 +526,11 @@ to_ruby_proc(SEXP robj, VALUE *obj)
513
526
  rb_intern("@@default_mode"),
514
527
  INT2FIX(BASIC_CONVERSION),Qtrue);
515
528
 
516
- *obj = rb_funcall(fun, rb_intern("call"), 1, tmp);
517
-
518
- //And reset mode
519
- rb_cvar_set(rb_const_get(rb_cObject,
520
- rb_intern("RSRuby")),
521
- rb_intern("@@default_mode"),
522
- mode,Qtrue);
523
-
529
+ //New safe code
530
+ args[0] = fun;
531
+ args[1] = tmp;
532
+ *obj = rb_ensure(call_proc,(VALUE) &args[0],reset_mode,mode);
533
+
524
534
  return 1; /* conversion succeed */
525
535
  }
526
536
 
@@ -567,7 +577,8 @@ VALUE from_class_table(SEXP robj)
567
577
  int
568
578
  to_ruby_class(SEXP robj, VALUE *obj)
569
579
  {
570
- VALUE fun, tmp;
580
+ VALUE fun, tmp, mode;
581
+ VALUE args[2];
571
582
 
572
583
  fun = from_class_table(robj);
573
584
 
@@ -577,8 +588,22 @@ to_ruby_class(SEXP robj, VALUE *obj)
577
588
  tmp = Data_Wrap_Struct(rb_const_get(rb_cObject,
578
589
  rb_intern("RObj")), 0, 0, robj);
579
590
  rb_iv_set(tmp,"@conversion",INT2FIX(TOP_MODE));
591
+ rb_iv_set(tmp,"@wrap",Qfalse);
592
+
593
+ //Again set conversion mode to basic to prevent recursion
594
+ mode = rb_cvar_get(rb_const_get(rb_cObject,
595
+ rb_intern("RSRuby")),
596
+ rb_intern("@@default_mode"));
597
+ rb_cvar_set(rb_const_get(rb_cObject,
598
+ rb_intern("RSRuby")),
599
+ rb_intern("@@default_mode"),
600
+ INT2FIX(BASIC_CONVERSION),Qtrue);
580
601
 
581
- *obj = rb_funcall(fun, rb_intern("call"), 1, tmp);
602
+ //New safe code
603
+ args[0] = fun;
604
+ args[1] = tmp;
605
+ *obj = rb_ensure(call_proc,(VALUE) &args[0],reset_mode,mode);
606
+ //*obj = rb_funcall(fun, rb_intern("call"), 1, tmp);
582
607
 
583
608
  return 1; /* conversion succeed */
584
609
  }
@@ -51,6 +51,9 @@ int to_ruby_class(SEXP robj, VALUE *obj);
51
51
  int from_proc_table(SEXP robj, VALUE *fun);
52
52
  VALUE from_class_table(SEXP robj);
53
53
 
54
+ VALUE call_proc(VALUE data);
55
+ VALUE reset_mode(VALUE mode);
56
+
54
57
  static VALUE to_ruby_hash(VALUE obj, SEXP names);
55
58
  static VALUE to_ruby_array(VALUE obj, int *dims, int l);
56
59
 
File without changes
File without changes
@@ -1,5 +1,4 @@
1
1
  require 'mkmf'
2
- require 'rbconfig'
3
2
 
4
3
  dir_config('R')
5
4
  unless have_library("R")
@@ -12,9 +11,3 @@ unless have_header("R.h")
12
11
  end
13
12
 
14
13
  create_makefile("rsruby")
15
- #create_makefile("robj")
16
-
17
- File.open("Makevars","w") do |file|
18
- file.puts "PKG_CPPFLAGS = -I#{Config::CONFIG["archdir"]} -D_R_=1 -DUSE_R=1 -DUSE_TOPLEVEL_EXEC=1"
19
- file.puts "PKG_LIBS = #{Config::CONFIG["LIBRUBYARG_SHARED"]}"
20
- end
File without changes
@@ -31,15 +31,6 @@
31
31
 
32
32
  #include "rsruby.h"
33
33
 
34
- //TODO - Cleanup and shutdown functions need implementing
35
- //static PyObject *
36
- //r_cleanup(void)
37
- //{
38
- // r_cleanup();
39
- // Py_INCREF(Py_None);
40
- // return Py_None;
41
- //}
42
-
43
34
  /* Global list to protect R objects from garbage collection */
44
35
  /* This is inspired in $R_SRC/src/main/memory.c */
45
36
  static SEXP R_References;
@@ -71,21 +62,6 @@ Robj_dealloc(VALUE self)
71
62
  return;
72
63
  }
73
64
 
74
- /*
75
- * Initialises the R interpreter.
76
- */
77
- void init_R(int argc, char **argv){
78
-
79
- int defaultArgc = 2;
80
- char *defaultArgv[] = {"Rtest","--silent"};
81
-
82
- if(argc == 0 || argv == NULL) {
83
- argc = defaultArgc;
84
- argv = defaultArgv;
85
- }
86
- Rf_initEmbeddedR(argc, argv);
87
- }
88
-
89
65
 
90
66
  /* Obtain an R object via its name.
91
67
  * This is only used to get the 'get' function.
@@ -112,6 +88,7 @@ VALUE get_fun(VALUE self, VALUE name){
112
88
  rubyobj = Data_Wrap_Struct(rb_const_get(rb_cObject,
113
89
  rb_intern("RObj")), 0, 0, robj);
114
90
  rb_iv_set(rubyobj,"@conversion",INT2FIX(conversion));
91
+ rb_iv_set(rubyobj,"@wrap",Qfalse);
115
92
 
116
93
  return rubyobj;
117
94
 
@@ -140,8 +117,6 @@ void r_finalize(void)
140
117
  VALUE cShutdown(VALUE self){
141
118
 
142
119
  r_finalize();
143
-
144
- self = Qnil;
145
120
  return Qtrue;
146
121
 
147
122
  }
@@ -162,6 +137,17 @@ VALUE rr_init(VALUE self){
162
137
 
163
138
  }
164
139
 
140
+ /*
141
+ * Initialises the R interpreter.
142
+ */
143
+ void init_R(int argc, char **argv){
144
+
145
+ int defaultArgc = 2;
146
+ char *defaultArgv[] = {"rsruby","-q","--vanilla"};
147
+
148
+ Rf_initEmbeddedR(defaultArgc, defaultArgv);
149
+ }
150
+
165
151
  /* Ruby code */
166
152
 
167
153
  VALUE cRRuby;
File without changes
data/lib/rsruby.rb CHANGED
@@ -1,116 +1,29 @@
1
+ require 'rsruby/robj'
2
+ require 'rsruby.so'
3
+ require 'singleton'
4
+
5
+ require 'complex'
6
+
1
7
  #== Synopsis
2
8
  #
3
- #This class provides the ability to embed a full R
4
- #interpreter inside a running Ruby script. R methods can
5
- #then be called from the Ruby script and data passed between the
6
- #R interpreter and the Ruby script. The code is based on a conversion
7
- #of the RSPerl[http://www.omegahat.org/RSPerl/] and RPy[http://rpy.sourceforge.net/]
8
- #modules which provide similar (and more) functionality for Perl and Python
9
- #respectively.
10
- #
11
- #The main RSRuby class has Singleton module mixed in. This ensures that only
12
- #one R interpreter is running in a script at any one time and that the
13
- #interpreter can always be found. The embedded R interpreter is started by
14
- #calling RSRuby.instance (See the RSRuby class for details). The returned
15
- #RSRuby object represents the R interpreter and R functions are called by
16
- #calling methods on this object.
17
- #
18
- #== Usage
19
- #
20
- # require 'rsruby'
21
- #
22
- # r = RSRuby.instance
23
- # puts r.sum(1,2,3)
24
- #
25
- #Converting between R and Ruby data types is handled in a similar way to
26
- #RPy and is explained in more detail in the manual (see Converters.c for the
27
- #gory details).
28
- #
29
- #The default conversion system mapping between R types and Ruby classes is
30
- #summarised here:
31
- #
32
- # - R Logicals (true/false) <=> Ruby true/false
33
- # - R Integers <=> Ruby Fixnum/Bignum
34
- # - R Real <=> Ruby Float
35
- # - R Complex <=> Ruby Complex
36
- # - R String <=> Ruby String
37
- # - R Vector <=> Ruby Array or Hash
38
- # - R List <=> Ruby Array or Hash
39
- # - R Array <=> Ruby Array or Hash
40
- # - R 'other' <=> Ruby RObj
41
- #
42
- #While this generally works fine for simple data structures, more complicated
43
- #structures can loose information when converted to Ruby. Clever use of the
44
- #more complicated custom conversion modes can usually avoid this.
45
- #
46
- #As shown above, calling R methods can be done by calling the same method
47
- #on the RSRuby object. Some R methods contain '.' and other characters
48
- #forbidden in Ruby method names. To call these methods substitute '_' for '.':
49
- #
50
- #Sample usage (to call R method 'as.list'):
51
- #
52
- # require 'rsruby'
53
- #
54
- # r = RSRuby.instance
55
- # puts r.as_list([1,2,3])
56
- #
57
- #If a Hash is the last argument to an RSRuby method call then the hash is
58
- #interpreted as a list of named arguments to the corresponding R function.
59
- #Argument names can be given as Strings or Symbols. Argument order is not
60
- #maintained in this case (because order is not maintained in Hashes). If
61
- #named arguments and order are required then there is the lcall syntax where
62
- #arguments are given as an array of two member arrays (where each two member
63
- #array represents a name/argument pair). lcall is a method defined in the
64
- #RObj class which represents functions and other non-convertible R objects.
65
- #
66
- #Calling an R method with no arguments returns the method object itself - it
67
- #does not call the method. This may be changed in the future as it is somewhat
68
- #confusing. However, the returned object can then be called or 'lcall'ed as
69
- #required. It is also possible to return R variables in this way:
70
- #
71
- #E.g.
72
- #
73
- # require 'rsruby'
74
- #
75
- # r = RSRuby.instance
76
- # norm = r.rnorm
77
- # norm_dist = norm.call(100)
78
- #
79
- # r.plot(norm_dist,
80
- # {:ylab => "TestY"})
81
- # sleep(2)
82
- #
9
+ #This class represents the embedded R interpreter. The Singleton module is
10
+ #mixed in to ensure that only one R interpreter is running in a script at
11
+ #any one time and that the interpreter can always be easily accessed without
12
+ #using a global variable.
83
13
  #
84
- #The final way to execute R code is to just evaluate a complete R expression
85
- #The eval_R method provides this functionality. Pass a String to the method to
86
- #see it evaluated by R:
14
+ #The R interpreter is started by calling RSRuby.instance. The returned
15
+ #object represents the R interpreter and R functions are called by
16
+ #calling methods on this object:
87
17
  #
88
- # require 'rsruby'
89
- #
90
- # r = RSRuby.instance
91
- # r.eval_R("a=43")
92
- # puts r.a
93
- #
94
- #As an alternative to the method syntax, R objects and functions can be
95
- #returned using []. This is required for weird R methods such as '$' or '[[':
96
- #
97
- # require 'rsruby'
98
- #
99
- # r = RSRuby.instance
100
- # r.eval_R("a=43")
101
- # puts r['a']
102
- #
103
- #R libraries can be loaded using the library method. Just provide the library
104
- #name as a String:
105
- #
106
- # require 'rsruby'
107
- #
108
- # r = RSRuby.instance
109
- # r.library("library_name")
110
- #
111
- #== Author
112
- #Alex Gutteridge
18
+ # r = RSRuby.instance
19
+ # r.sum(1,2,3)
20
+ # puts r.t_test(1,2,3)['p-value']
113
21
  #
22
+ #See the manual[http://web.kuicr.kyoto-u.ac.jp/~alexg/rsruby/manual.pdf] for
23
+ #more details on calling functions and the conversion system for passing data
24
+ #between Ruby and R. If no suitable conversion from R to Ruby is found, an RObj
25
+ #is returned (all R functions are returned as instances of RObj).
26
+ #--
114
27
  #== Copyright
115
28
  #Copyright (C) 2006 Alex Gutteridge
116
29
  #
@@ -136,18 +49,12 @@
136
49
  #You should have received a copy of the GNU Lesser General Public
137
50
  #License along with this library; if not, write to the Free Software
138
51
  #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
139
-
140
- require 'rsruby/robj'
141
- require 'rsruby.so'
142
- require 'singleton'
143
-
144
- require 'complex'
145
-
146
- class RException < RuntimeError
147
- end
52
+ #++
148
53
 
149
54
  class RSRuby
150
55
 
56
+ VERSION = '0.4.2'
57
+
151
58
  include Singleton
152
59
 
153
60
  #Constants for conversion modes
@@ -223,7 +130,7 @@ class RSRuby
223
130
 
224
131
  end
225
132
 
226
- #As method_missing, but only returns the R function/object
133
+ #The same as method_missing, but only returns the R function/object,
227
134
  #does not call it.
228
135
  def [](r_id)
229
136
 
@@ -245,7 +152,8 @@ class RSRuby
245
152
  return func
246
153
  end
247
154
 
248
- #Converts method names from Ruby compatible style into R style.
155
+ #Converts a String representing a 'Ruby-style' R function name into a
156
+ #String with the real R name according to the rules given in the manual.
249
157
  def RSRuby.convert_method_name(name)
250
158
  if name.length > 1 and name[-1].chr == '_' and name[-2].chr != '_'
251
159
  name = name[0..-2]
@@ -255,10 +163,16 @@ class RSRuby
255
163
  return name
256
164
  end
257
165
 
258
- #Converts an array of arguments into lcall format. If the last element
259
- #of the array is a Hash then the contents are interpreted as named
260
- #arguments. lcall format is an Array of two member Arrays. Each two
261
- #member array corresponds to a name/argument pair.
166
+ #Converts an Array of function arguments into lcall format. If the last
167
+ #element of the array is a Hash then the contents of the Hash are
168
+ #interpreted as named arguments.
169
+ #
170
+ #The returned value is an Array of tuples (Arrays of length two). Each
171
+ #tupple corresponds to a name/argument pair.
172
+ #
173
+ #For example:
174
+ # convert_args_to_lcall([1,2,3,{:a=>4,:b=>5})
175
+ # => [['',1],['',2],['',3],['a',4],['b',5]]
262
176
  def RSRuby.convert_args_to_lcall(args)
263
177
 
264
178
  lcall_args = []
@@ -290,24 +204,32 @@ class RSRuby
290
204
  @@default_mode
291
205
  end
292
206
 
293
- #TODO - input/output setting methods don't work atm
207
+ #TODO - not implemented
294
208
  def RSRuby.set_rsruby_input(m)
295
209
  @@rsruby_input = m
296
210
  end
211
+
212
+ #TODO - not implemented
297
213
  def RSRuby.get_rsruby_input
298
214
  @@rsruby_input
299
215
  end
300
216
 
217
+ #TODO - not implemented
301
218
  def RSRuby.set_rsruby_output(m)
302
219
  @@rsruby_output = m
303
220
  end
221
+
222
+ #TODO - not implemented
304
223
  def RSRuby.get_rsruby_output
305
224
  @@rsruby_output
306
225
  end
307
226
 
227
+ #TODO - not implemented
308
228
  def RSRuby.set_rsruby_showfiles(m)
309
229
  @@rsruby_showfiles = m
310
230
  end
231
+
232
+ #TODO - not implemented
311
233
  def RSRuby.get_rsruby_showfiles
312
234
  @@rsruby_showfiles
313
235
  end
@@ -343,7 +265,6 @@ class RSRuby
343
265
  self.print(helpobj)
344
266
  end
345
267
 
346
- :private
347
268
  def __getitem__(name)
348
269
 
349
270
  #Find the identifier and cache (unless already cached)
@@ -359,3 +280,6 @@ class RSRuby
359
280
  end
360
281
 
361
282
  end
283
+
284
+ class RException < RuntimeError
285
+ end