00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "RConfigOptions.h"
00012 #include "TROOT.h"
00013 #include "TClass.h"
00014 #include "TApplication.h"
00015 #include "TSystem.h"
00016 #include "TRandom.h"
00017 #include "TF2.h"
00018 #include "TBenchmark.h"
00019 #include "TVirtualPad.h"
00020 #include "TStyle.h"
00021
00022 #include "CallFunc.h"
00023 #include "Class.h"
00024
00025 #include "ruby.h"
00026
00027 #include "rrcommon.h"
00028
00029
00030 #include "rrenums.h"
00031
00032
00033 #if defined(linux) || defined(sun)
00034 #include "dlfcn.h"
00035 #endif
00036
00037 #if ((R__RUBY_MAJOR<1) || (R__RUBY_MAJOR==1)&&(R__RUBY_MINOR<=9))
00038 # define rb_frame_this_func rb_frame_last_func
00039 #endif
00040
00041
00042 VALUE cTObject;
00043
00044 VALUE rr_ary_new (TList *l)
00045 {
00046
00047 VALUE arr = rb_ary_new();
00048 VALUE o;
00049
00050 TObject *rro;
00051 TIter next (l);
00052
00053 while ((rro = next()))
00054 {
00055 RRNEW(o, cTObject);
00056 rb_iv_set (o, "__rr__", Data_Wrap_Struct (cTObject, 0, 0, rro));
00057 rb_iv_set (o, "__rr_class__",
00058 rb_str_new2(rro->ClassName()));
00059 rb_ary_push (arr, o);
00060 }
00061
00062 return arr;
00063 }
00064
00065 static VALUE rr_to_ary (VALUE self)
00066 {
00067
00068 RRGRAB(self, TList, l);
00069 return rr_ary_new (l);
00070 }
00071
00072 VALUE rr_arrayc_new (const TArrayC *a)
00073 {
00074
00075 VALUE arr = rb_ary_new();
00076
00077 for (int i = 0; i < a->GetSize(); i++)
00078 rb_ary_push (arr, INT2NUM(a->At(i)));
00079
00080 return arr;
00081 }
00082
00083 VALUE rr_arrays_new (const TArrayS *a)
00084 {
00085
00086 VALUE arr = rb_ary_new();
00087
00088 for (int i = 0; i < a->GetSize(); i++)
00089 rb_ary_push (arr, INT2NUM(a->At(i)));
00090
00091 return arr;
00092 }
00093
00094 VALUE rr_arrayi_new (const TArrayI *a)
00095 {
00096
00097 VALUE arr = rb_ary_new();
00098
00099 for (int i = 0; i < a->GetSize(); i++)
00100 rb_ary_push (arr, INT2NUM(a->At(i)));
00101
00102 return arr;
00103 }
00104
00105 VALUE rr_arrayl_new (const TArrayL *a)
00106 {
00107
00108 VALUE arr = rb_ary_new();
00109
00110 for (int i = 0; i < a->GetSize(); i++)
00111 rb_ary_push (arr, INT2NUM(a->At(i)));
00112
00113 return arr;
00114 }
00115
00116 VALUE rr_arrayf_new (const TArrayF *a)
00117 {
00118
00119 VALUE arr = rb_ary_new();
00120
00121 for (int i = 0; i < a->GetSize(); i++)
00122 rb_ary_push (arr, rb_float_new(a->At(i)));
00123
00124 return arr;
00125 }
00126
00127 VALUE rr_arrayd_new (const TArrayD *a)
00128 {
00129
00130 VALUE arr = rb_ary_new();
00131
00132 for (int i = 0; i < a->GetSize(); i++)
00133 rb_ary_push (arr, rb_float_new(a->At(i)));
00134
00135 return arr;
00136 }
00137
00138 VALUE rr_seqcollection_new (TSeqCollection *sc)
00139 {
00140
00141 VALUE arr = rb_ary_new();
00142 VALUE o;
00143
00144 for (int i = 0; i < sc->GetSize(); i++)
00145 {
00146 RRNEW(o, cTObject);
00147 rb_iv_set (o, "__rr__", Data_Wrap_Struct (cTObject, 0, 0, sc->At(i)));
00148 rb_ary_push (arr, o);
00149 }
00150
00151 return arr;
00152 }
00153
00154 void * rr_parse_void (VALUE o)
00155 {
00156 VALUE *i;
00157
00158 switch (TYPE(o))
00159 {
00160 case T_STRING:
00161 return (void *) RSTRING(o)->ptr;
00162 case T_FLOAT:
00163 return (void *) &RFLOAT(o)->value;
00164 case T_FIXNUM:
00165
00166
00167
00168 i = (VALUE*) malloc (sizeof(int));
00169 *i = (int) (o>>1);
00170 return (void *) i;
00171 case T_OBJECT:
00172 RRGRAB(o, void *, res);
00173 return res;
00174 default:
00175 rb_fatal ("Failed convertion of %d to void *.\n",
00176 STR2CSTR(CLASS_OF(o)));
00177 break;
00178 }
00179
00180 return (void *) NULL;
00181 }
00182
00183 VALUE rr_bool (bool q)
00184 {
00185 VALUE res = Qnil;
00186
00187 q == 0 ? res = Qfalse : res = Qtrue;
00188
00189 return res;
00190 }
00191
00192
00193
00194
00195 static struct rr_fcn_info * rr_tf1_table[256];
00196 static int rr_tf1_tblptr = 0;
00197
00198 double rr_ctf1_fcn (double *x, double* par)
00199 {
00200 TF1 *fcn = (TF1 *)TF1::GetCurrent();
00201 struct rr_fcn_info *info = NULL;
00202
00203 for (int i = 0; i < rr_tf1_tblptr; i++)
00204 {
00205 info = rr_tf1_table[i];
00206 if (!strcmp(info->name, fcn->GetName()))
00207 break;
00208 else
00209 info = NULL;
00210 }
00211
00212 if (info == NULL)
00213 rb_warn("Ruby user defined function has not been registered for %s (%p).",
00214 fcn->GetName(), fcn);
00215
00216 int n = fcn->GetNpar();
00217 VALUE vx = rb_ary_new2 (n);
00218 VALUE vpar = rb_ary_new2 (n);
00219 for (int i = 0; i < n; i++)
00220 {
00221 rb_ary_push (vx, rb_float_new(x[i]));
00222 rb_ary_push (vpar, rb_float_new(par[i]));
00223 }
00224
00225 double res = NUM2DBL(rb_funcall (rb_cObject, info->id, 2, vx, vpar));
00226 return res;
00227 }
00228
00229 void rr_register_ctf1_fcn (char *name, ID id)
00230 {
00231 struct rr_fcn_info *info = (struct rr_fcn_info *)malloc (sizeof *info);
00232
00233 info->name = strdup(name);
00234 info->id = id;
00235
00236 rr_tf1_table[rr_tf1_tblptr] = info;
00237 rr_tf1_tblptr++;
00238
00239 }
00240
00241 static struct rr_fcn_info * rr_tf2_table[256];
00242 static int rr_tf2_tblptr = 0;
00243
00244 double rr_ctf2_fcn (double *x, double* par)
00245 {
00246 TF2 *fcn = (TF2 *)TF2::GetCurrent();
00247 struct rr_fcn_info *info = NULL;
00248
00249 for (int i = 0; i < rr_tf2_tblptr; i++)
00250 {
00251 info = rr_tf2_table[i];
00252 if (!strcmp(info->name, fcn->GetName()))
00253 break;
00254 else
00255 info = NULL;
00256 }
00257
00258 if (info == NULL)
00259 rb_warn("Ruby user defined function has not been registered for %s (%p).",
00260 fcn->GetName(), fcn);
00261
00262 int n = fcn->GetNpar();
00263 VALUE vx = rb_ary_new2 (n);
00264 VALUE vpar = rb_ary_new2 (n);
00265 for (int i = 0; i < n; i++)
00266 {
00267 rb_ary_push (vx, rb_float_new(x[i]));
00268 rb_ary_push (vpar, rb_float_new(par[i]));
00269 }
00270
00271 double res = NUM2DBL(rb_funcall (rb_cObject, info->id, 2, vx, vpar));
00272 return res;
00273 }
00274
00275 void rr_register_ctf2_fcn (char *name, ID id)
00276 {
00277 struct rr_fcn_info *info = (struct rr_fcn_info *)malloc (sizeof *info);
00278
00279 info->name = strdup(name);
00280 info->id = id;
00281
00282 rr_tf2_table[rr_tf2_tblptr] = info;
00283 rr_tf2_tblptr++;
00284
00285 }
00286
00287
00288
00289
00290 static VALUE rr_gsystem (void)
00291 {
00292 VALUE o;
00293
00294 RRNEW(o, cTObject);
00295 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gSystem));
00296 rb_iv_set (o, "__rr_class__", rb_str_new2("TSystem"));
00297
00298 return o;
00299 }
00300
00301 static VALUE rr_grandom (void)
00302 {
00303 VALUE o;
00304
00305 RRNEW(o, cTObject);
00306 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gRandom));
00307 rb_iv_set (o, "__rr_class__", rb_str_new2("TRandom"));
00308
00309 return o;
00310 }
00311
00312 static VALUE rr_gbenchmark (void)
00313 {
00314 VALUE o;
00315
00316 RRNEW(o, cTObject);
00317 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gBenchmark));
00318 rb_iv_set (o, "__rr_class__", rb_str_new2("TBenchmark"));
00319
00320 return o;
00321 }
00322
00323 static VALUE rr_gpad (void)
00324 {
00325 VALUE o;
00326
00327 RRNEW(o, cTObject);
00328 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gPad));
00329 rb_iv_set (o, "__rr_class__", rb_str_new2("TPad"));
00330
00331 return o;
00332 }
00333
00334 static VALUE rr_gstyle (void)
00335 {
00336 VALUE o;
00337
00338 RRNEW(o, cTObject);
00339 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gStyle));
00340 rb_iv_set (o, "__rr_class__", rb_str_new2("TStyle"));
00341
00342 return o;
00343 }
00344
00345 static VALUE rr_gdirectory (void)
00346 {
00347 VALUE o;
00348
00349 RRNEW(o, cTObject);
00350 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gDirectory));
00351 rb_iv_set (o, "__rr_class__", rb_str_new2("TDirectory"));
00352
00353 return o;
00354 }
00355
00356 static VALUE rr_groot (void)
00357 {
00358 VALUE o;
00359
00360 RRNEW(o, cTObject);
00361
00362 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gROOT));
00363 rb_iv_set (o, "__rr_class__", rb_str_new2("TROOT"));
00364
00365 return o;
00366 }
00367
00368 static VALUE rr_gapplication (void)
00369 {
00370 VALUE o;
00371
00372 RRNEW(o, cTObject);
00373
00374 rb_iv_set (o, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, gApplication));
00375 rb_iv_set (o, "__rr_class__", rb_str_new2("TApplication"));
00376
00377 return o;
00378 }
00379
00380 static VALUE via (VALUE self, VALUE ameth, VALUE bmeth, VALUE parms)
00381 {
00382 if (TYPE(ameth) != T_SYMBOL &&
00383 TYPE(bmeth) != T_SYMBOL &&
00384 TYPE(parms) != T_HASH)
00385 {
00386 rb_fatal ("rr-via: Please call TObject#via with sym, sym, hash.");
00387 return Qnil;
00388 }
00389
00390 VALUE keys = rb_funcall(parms, rb_intern("keys"), 0);
00391 for (int i = 0; i < RARRAY(keys)->len; i++)
00392 {
00393 VALUE key = rb_ary_entry (keys, i);
00394 rb_funcall (self, rb_to_id (ameth), 2, key, rb_hash_aref (parms, key));
00395 }
00396 rb_funcall(self, rb_to_id(bmeth), 0);
00397
00398 return self;
00399 }
00400
00401
00402
00403 TObject* drr_grab_object(VALUE self)
00404 {
00405 static TObject *o;
00406 Data_Get_Struct(rb_iv_get (self, "__rr__"), TObject, o);
00407 return o;
00408 }
00409
00410 unsigned int drr_map_args2(VALUE inargs, char *cproto, G__CallFunc *f, long int offset=1, unsigned int reference_map=0x0)
00411 {
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 int nargs = RARRAY(inargs)->len - offset;
00424 double *arr = NULL;
00425 TObject *ptr = NULL;
00426 VALUE v = 0;
00427
00428 unsigned int ntobjects = 0;
00429
00430
00431 for (int i = 0; i < nargs; i++)
00432 {
00433 VALUE arg = rb_ary_entry (inargs, i+offset);
00434 switch (TYPE(arg))
00435 {
00436 case T_FIXNUM:
00437 if (f) f->SetArg((long) NUM2INT(arg));
00438 if (cproto) strcat(cproto, "int");
00439 break;
00440 case T_FLOAT:
00441 if (f) f->SetArg(NUM2DBL(arg));
00442 if (cproto) strcat(cproto, "double");
00443 break;
00444 case T_STRING:
00445 if (f) f->SetArg((long) STR2CSTR(arg));
00446 if (cproto) strcat(cproto, "char*");
00447 break;
00448 case T_ARRAY:
00449
00450
00451
00452 if (f)
00453 {
00454 arr = ALLOC_N (double, RARRAY(arg)->len);
00455 for (int j = 0; j < RARRAY(arg)->len; j++)
00456 arr[j] = NUM2DBL(rb_ary_entry (arg, j));
00457 f->SetArg((long) arr);
00458 }
00459 if (cproto) strcat(cproto, "double*");
00460 break;
00461 case T_OBJECT:
00462 v = rb_iv_get (arg, "__rr__");
00463 if (!NIL_P(v))
00464 {
00465 Data_Get_Struct (v, TObject, ptr);
00466 if (f) f->SetArg((long) ptr);
00467 if (cproto) {
00468 strcat(cproto, STR2CSTR(rb_iv_get (arg, "__rr_class__")));
00469 if( ((reference_map>>ntobjects)&0x1) ) {
00470 strcat(cproto, "*");
00471 } else {
00472 strcat(cproto, "&");
00473 }
00474 }
00475 }
00476 ++ntobjects;
00477 break;
00478 default:
00479 break;
00480 }
00481 if ((i + 1 < nargs) && (nargs != 1) && cproto)
00482 strcat(cproto, ",");
00483 }
00484 return ntobjects;
00485 }
00486
00487 void drr_find_method_prototype( G__ClassInfo *klass, char *methname, VALUE inargs, char *cproto, long int offset=1 )
00488 {
00489
00490
00491
00492
00493
00494 G__MethodInfo *minfo = 0;
00495 long int dummy_offset = 0;
00496
00497
00498 unsigned int nobjects = drr_map_args2 (inargs, cproto, 0, offset, 0x0);
00499
00500 unsigned int bitmap_end = static_cast<unsigned int>( 0x1 << nobjects );
00501
00502
00503 minfo = new G__MethodInfo(klass->GetMethod(methname, cproto, &dummy_offset));
00504
00505
00506
00507
00508 if( nobjects > 0 and !(minfo->InterfaceMethod()) ) {
00509 for( unsigned int reference_map=0x1; reference_map < bitmap_end; reference_map++) {
00510 cproto[0] = static_cast<char>( 0 );
00511 drr_map_args2 (inargs, cproto, 0, offset, reference_map);
00512 minfo = new G__MethodInfo(klass->GetMethod(methname, cproto, &dummy_offset));
00513 if (minfo->InterfaceMethod())
00514 break;
00515 }
00516 }
00517
00518 delete minfo;
00519
00520 return;
00521 }
00522
00523 void drr_set_method_args( VALUE inargs, G__CallFunc *func, long int offset=1 )
00524 {
00525 drr_map_args2( inargs, 0, func, offset );
00526 }
00527
00528 enum ktype {kint, kfloat, kchar, kunknown, kvoid, kintary, kfloatary, kstring, kroot, kbool};
00529
00530 int drr_parse_ret_type (const char *ret)
00531 {
00532 char *realtype = strdup(ret), *t = realtype;
00533 int plevel = 0;
00534 enum ktype type;
00535
00536 while (*(t++)) {
00537 if (*t == '*')
00538 plevel++;
00539 }
00540
00541 t--;
00542
00543 if (plevel > 0)
00544 *(t - plevel) = '\0';
00545
00546 if (!strncmp(t - 3, "int", 3) ||
00547 !strncmp(t - 4, "long", 4))
00548 type = kint;
00549 else
00550 if (!strncmp(t - 6, "double", 6) ||
00551 !strncmp(t - 5, "float", 5))
00552 type = kfloat;
00553 else
00554 if (!strncmp(t - 5, "char", 4))
00555 type = kchar;
00556 else
00557 if (!strncmp(t - 4, "void", 4))
00558 type = kvoid;
00559 else
00560 if (!strncmp(t - 4, "bool", 4))
00561 type = kbool;
00562 else
00563 type = kunknown;
00564
00565 if (plevel)
00566
00567
00568
00569 type = (enum ktype)(type + 5);
00570
00571 free (realtype);
00572
00573 return type;
00574 }
00575
00576
00577
00578 struct drr_func_cache * drr_func_cache_init(struct drr_func_entry *entry)
00579 {
00580 struct drr_func_cache *new_cache = (struct drr_func_cache *) malloc (sizeof *new_cache);
00581 new_cache->next = NULL;
00582 new_cache->entry = entry;
00583 new_cache->last = NULL;
00584 return new_cache;
00585 }
00586
00587 void drr_func_cache_push (struct drr_func_cache *cache, struct drr_func_entry *entry)
00588 {
00589 struct drr_func_cache *n = (struct drr_func_cache *) malloc(sizeof *n);
00590 n->entry = entry;
00591
00592 if (cache->next)
00593 {
00594 n->next = cache->next;
00595 cache->next = n;
00596 }
00597 else
00598 {
00599 cache->next = n;
00600 n->next = NULL;
00601 }
00602 }
00603
00604 struct drr_func_entry * drr_func_cache_find (struct drr_func_cache *cache, char *name)
00605 {
00606 struct drr_func_cache *iter = cache;
00607
00608 while (iter)
00609 {
00610 if (!strcmp (iter->entry->name, name))
00611 return iter->entry;
00612 iter = iter->next;
00613 }
00614 return NULL;
00615 }
00616
00617 void drr_func_entry_free (struct drr_func_entry *entry)
00618 {
00619 delete entry->func;
00620 delete entry->klass;
00621 free (entry->name);
00622 free (entry->cproto);
00623 free (entry);
00624 }
00625
00626
00627
00628 VALUE drrAbstractClass;
00629
00630 static VALUE drr_as(VALUE self, VALUE klass)
00631 {
00632
00633 VALUE v;
00634
00635
00636 TClass *c = TClass::GetClass(STR2CSTR(klass));
00637 if (c)
00638 {
00639 VALUE k;
00640 char *name = STR2CSTR(klass);
00641 if (!rb_const_defined (rb_cObject, rb_intern(name)))
00642 k = rb_define_class (name, drrAbstractClass);
00643 else
00644 k = rb_path2class (name);
00645
00646 RRNEW(v, k);
00647 rb_iv_set (v, "__rr__", rb_iv_get(self, "__rr__"));
00648 rb_iv_set (v, "__rr_class__", klass);
00649 }
00650 else
00651 rb_raise( rb_eArgError, "No TClass found for %s. Is this a Root type?", STR2CSTR(klass) );
00652
00653 return v;
00654 }
00655
00656 static VALUE drr_init(int argc, VALUE argv[], VALUE self)
00657 {
00658 VALUE inargs;
00659 char *classname = (char*) rb_obj_classname(self);
00660 char cproto[1024] = "";
00661 long addr = 0, offset;
00662
00663 rb_scan_args (argc, argv, "0*", &inargs);
00664
00665 G__CallFunc func;
00666 G__ClassInfo klass(classname);
00667
00668
00669
00670 if (RARRAY(inargs)->len) {
00671 drr_find_method_prototype (&klass, classname, inargs, cproto, 0);
00672 drr_set_method_args ( inargs, &func, 0);
00673 }
00674
00675 G__MethodInfo minfo(klass.GetMethod(classname, cproto, &offset));
00676 if (minfo.InterfaceMethod())
00677 func.SetFunc(minfo);
00678 else
00679 rb_raise( rb_eArgError, "You provided an unknown prototype (%s) for (%s#%s).",
00680 cproto, classname, classname);
00681
00682 addr = func.ExecInt((void*)((long)0 + offset));
00683 rb_iv_set(self, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, (TObject *)addr));
00684 rb_iv_set(self, "__rr_class__", rb_str_new2 (classname));
00685
00686 func.Init();
00687 return self;
00688 }
00689
00690 static VALUE drr_return(int rtype, long value_address, double dvalue_address, VALUE self)
00691 {
00692 VALUE vret;
00693
00694 switch (rtype)
00695 {
00696 case kint:
00697 vret = INT2NUM(value_address);
00698 break;
00699 case kfloat:
00700 vret = rb_float_new(dvalue_address);
00701 break;
00702 case kstring:
00703 vret = rb_str_new2((char *)value_address);
00704 break;
00705 case kbool:
00706 vret = rr_bool((bool)value_address);
00707 break;
00708 case kroot:
00709 if (!value_address)
00710 return Qnil;
00711
00712 if (!strcmp(((TObject*)(value_address))->ClassName(), "TList"))
00713 vret = rr_ary_new((TList*)value_address);
00714 else
00715 {
00716 VALUE res;
00717 RRNEW(res, cTObject);
00718 rb_iv_set(res, "__rr__", Data_Wrap_Struct(cTObject, 0, 0, (TObject*)value_address));
00719 rb_iv_set(res, "__rr_class__", rb_str_new2 (((TObject*)(value_address))->ClassName()));
00720 vret = res;
00721 }
00722
00723 break;
00724
00725 default:
00726 vret = self;
00727 break;
00728 }
00729
00730 return vret;
00731 }
00732
00733
00734 static VALUE drr_const_missing(VALUE self, VALUE klass)
00735 {
00736
00737
00738 char *name = (char*) rb_id2name (rb_to_id(klass));
00739
00740
00741 TClass *c = new TClass(name);
00742 if (c && c->GetClassInfo()) {
00743 VALUE new_klass = rb_define_class (name, drrAbstractClass);
00744 delete c;
00745 return new_klass;
00746 } else {
00747 delete c;
00748
00749 return rb_funcall(self,rb_intern("__drr_orig_const_missing"),1,klass);
00750 }
00751 }
00752
00753 static VALUE drr_singleton_missing(int argc, VALUE argv[], VALUE self)
00754 {
00755 VALUE inargs;
00756 char cproto[1024] = "";
00757 int nargs;
00758 long offset, address = 0;
00759 double dbladdr = 0;
00760
00761
00762 char * methname = (char*) rb_id2name (rb_to_id(argv[0]));
00763 char * classname = (char *) rb_class2name(self);
00764
00765 rb_scan_args (argc, argv, "0*", &inargs);
00766 nargs = RARRAY(inargs)->len - 1;
00767
00768 G__CallFunc *func = new G__CallFunc();
00769 G__ClassInfo *klass = new G__ClassInfo (classname);
00770 G__MethodInfo *minfo = 0;
00771
00772 if (nargs) {
00773 drr_find_method_prototype( klass, methname, inargs, cproto, 1 );
00774 drr_set_method_args( inargs, func, 1 );
00775 }
00776
00777
00778 minfo = new G__MethodInfo(klass->GetMethod(methname, cproto, &offset));
00779 if (minfo->InterfaceMethod())
00780 func->SetFunc(*minfo);
00781 else
00782 rb_raise( rb_eArgError, "You provided an unknown prototype (%s) for (%s#%s).",
00783 cproto, classname, methname);
00784
00785 delete minfo;
00786
00787 int rtype = drr_parse_ret_type (minfo->Type()->TrueName());
00788
00789 if (rtype != kfloat)
00790 address = func->ExecInt((void*)(offset));
00791 else
00792 dbladdr = func->ExecDouble((void*)(offset));
00793
00794 return(drr_return(rtype, address, dbladdr, self));
00795 }
00796
00797
00798 static VALUE drr_method_missing(int argc, VALUE argv[], VALUE self)
00799 {
00800
00801
00802
00803
00804
00805
00806 VALUE inargs;
00807 char *methname, *classname ;
00808 long offset, address = 0;
00809 double dbladdr = 0;
00810 char cproto[1024] = "";
00811 int nargs;
00812
00813
00814 methname = (char*) rb_id2name (rb_to_id(argv[0]));
00815 classname = STR2CSTR(rb_iv_get (self, "__rr_class__"));
00816 TObject *caller = drr_grab_object (self);
00817
00818 rb_scan_args (argc, argv, "0*", &inargs);
00819
00820 nargs = RARRAY(inargs)->len - 1;
00821 VALUE rklass = rb_class_of (self);
00822
00823 G__CallFunc *func = new G__CallFunc();
00824 G__ClassInfo *klass = new G__ClassInfo (classname);
00825 G__MethodInfo *minfo = 0;
00826
00827 if (nargs) {
00828 drr_find_method_prototype( klass, methname, inargs, cproto, 1 );
00829 drr_set_method_args( inargs, func, 1 );
00830 }
00831
00832
00833 minfo = new G__MethodInfo(klass->GetMethod(methname, cproto, &offset));
00834 if (minfo->InterfaceMethod())
00835 func->SetFunc(*minfo);
00836 else
00837 rb_raise( rb_eArgError, "You provided an unknown prototype (%s) for (%s#%s).",
00838 cproto, classname, methname);
00839
00840
00841 struct drr_func_entry *entry = (struct drr_func_entry *) malloc (sizeof *entry);
00842 entry->func = func;
00843 entry->klass = klass;
00844 entry->name = strdup(methname);
00845 entry->cproto = strdup(cproto);
00846 entry->rtype = drr_parse_ret_type (minfo->Type()->TrueName());
00847
00848 delete minfo;
00849
00850 struct drr_func_cache *cache;
00851
00852 if (!rb_cvar_defined (rklass, rb_intern("@@__func_table__")))
00853 cache = drr_func_cache_init (entry);
00854 else
00855 Data_Get_Struct(rb_cv_get(rklass, "@@__func_table__"), struct drr_func_cache, cache);
00856
00857
00858 drr_func_cache_push (cache, entry);
00859 rb_cv_set (rklass, "@@__func_table__",
00860 Data_Wrap_Struct(cTObject, 0, 0, cache));
00861
00862 if (entry->rtype != kfloat)
00863 address = func->ExecInt((void*)((long)caller + offset));
00864 else
00865 dbladdr = func->ExecDouble((void*)((long)caller + offset));
00866
00867
00868 rb_define_method (rklass, methname, VALUEFUNC(drr_generic_method), -1);
00869
00870 return(drr_return(entry->rtype, address, dbladdr, self));
00871 }
00872
00873 static VALUE drr_generic_method(int argc, VALUE argv[], VALUE self)
00874 {
00875 VALUE inargs;
00876 VALUE rklass;
00877 int nargs;
00878 long offset = 0, address = 0;
00879 double dbladdr = 0;
00880 char cproto[1024] = "";
00881
00882
00883 rklass = rb_class_of (self);
00884 char *methname = (char*) rb_id2name (rb_frame_this_func());
00885 TObject *caller = drr_grab_object (self);
00886
00887 rb_scan_args (argc, argv, "0*", &inargs);
00888
00889 nargs = RARRAY(inargs)->len;
00890
00891 G__CallFunc *func = NULL;
00892
00893 struct drr_func_cache *cache;
00894 struct drr_func_entry *entry;
00895
00896 Data_Get_Struct (rb_cv_get(rklass, "@@__func_table__"), struct drr_func_cache, cache);
00897 entry = drr_func_cache_find (cache, methname);
00898
00899 if (entry)
00900 {
00901 func = entry->func;
00902 if (nargs)
00903 drr_find_method_prototype (entry->klass, methname, inargs, cproto, 0);
00904 func->SetFuncProto (entry->klass, methname, cproto, &offset);
00905
00906
00907
00908 if (nargs)
00909 drr_set_method_args (inargs, func, 0);
00910 }
00911 else
00912
00913 rb_warn ("Proto conflict with cache. Expected %s, but found: %s", cproto, entry->cproto);
00914
00915 if (entry->rtype != kfloat)
00916 address = func->ExecInt((void*)((long)caller + offset));
00917 else
00918 dbladdr = func->ExecDouble((void*)((long)caller + offset));
00919
00920 return(drr_return(entry->rtype, address, dbladdr, self));
00921 }
00922
00923 extern "C"
00924 void Init_libRuby() {
00925
00926
00927
00928 #if defined(linux) || defined(sun)
00929 dlopen( "libCint.so", RTLD_GLOBAL | RTLD_LAZY );
00930 dlopen( "libCore.so", RTLD_GLOBAL | RTLD_LAZY );
00931 dlopen( "libGpad.so", RTLD_GLOBAL | RTLD_LAZY );
00932 dlopen( "libGraf.so", RTLD_GLOBAL | RTLD_LAZY );
00933 dlopen( "libMatrix.so", RTLD_GLOBAL | RTLD_LAZY );
00934 dlopen( "libHist.so", RTLD_GLOBAL | RTLD_LAZY );
00935 dlopen( "libTree.so", RTLD_GLOBAL | RTLD_LAZY );
00936 dlopen( "libGraf3d.so", RTLD_GLOBAL | RTLD_LAZY );
00937 dlopen( "libGeom.so", RTLD_GLOBAL | RTLD_LAZY );
00938 #endif
00939
00940
00941 if (!gApplication)
00942 gApplication = new TApplication("ruby root app", NULL, NULL);
00943
00944 drrAbstractClass = rb_define_class("DRRAbstractClass", rb_cObject);
00945 rb_define_method(drrAbstractClass, "initialize", VALUEFUNC(drr_init), -1);
00946 rb_define_method(drrAbstractClass, "method_missing", VALUEFUNC(drr_method_missing), -1);
00947 rb_define_method (drrAbstractClass, "as", VALUEFUNC(drr_as), 1);
00948
00949 rb_define_singleton_method (drrAbstractClass, "method_missing", VALUEFUNC(drr_singleton_missing), -1);
00950
00951 cTObject = rb_define_class("TObject", drrAbstractClass);
00952
00953 rb_define_method (cTObject, "to_ary", VALUEFUNC(rr_to_ary), 0);
00954 rb_define_method (rb_cObject, "via", VALUEFUNC(via), 3);
00955
00956
00957
00958 rb_eval_string("Object.instance_eval { alias __drr_orig_const_missing const_missing }");
00959 rb_define_singleton_method (rb_cObject, "const_missing", VALUEFUNC(drr_const_missing), 1);
00960
00961
00962 rb_define_method (rb_cObject, "gSystem", VALUEFUNC(rr_gsystem), 0);
00963 rb_define_method (rb_cObject, "gRandom", VALUEFUNC(rr_grandom), 0);
00964 rb_define_method (rb_cObject, "gBenchmark", VALUEFUNC(rr_gbenchmark), 0);
00965 rb_define_method (rb_cObject, "gPad", VALUEFUNC(rr_gpad), 0);
00966 rb_define_method (rb_cObject, "gStyle", VALUEFUNC(rr_gstyle), 0);
00967 rb_define_method (rb_cObject, "gDirectory", VALUEFUNC(rr_gdirectory), 0);
00968 rb_define_method (rb_cObject, "gROOT", VALUEFUNC(rr_groot), 0);
00969 rb_define_method (rb_cObject, "gApplication", VALUEFUNC(rr_gapplication), 0);
00970
00971
00972 init_global_enums();
00973 }