TMethodCall.cxx

Go to the documentation of this file.
00001 // @(#)Root/meta:$Id: TMethodCall.cxx 29701 2009-08-06 15:27:35Z pcanal $
00002 // Author: Fons Rademakers   13/06/96
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TMethodCall                                                          //
00015 //                                                                      //
00016 // Method or function calling interface. Objects of this class contain  //
00017 // the (CINT) environment to call a global function or a method for an  //
00018 // object of a specific class with the desired arguments. This class is //
00019 // espicially useful when a method has to be called more times for      //
00020 // different objects and/or with different arguments. If a function or  //
00021 // method needs to be called only once one better uses                  //
00022 // TInterpreter::Execute().                                             //
00023 //                                                                      //
00024 //////////////////////////////////////////////////////////////////////////
00025 
00026 #include "TInterpreter.h"
00027 #include "TMethodCall.h"
00028 #include "TMethod.h"
00029 #include "TClass.h"
00030 #include "TROOT.h"
00031 #include "Strlen.h"
00032 #include "TVirtualMutex.h"
00033 
00034 ClassImp(TMethodCall)
00035 
00036 //______________________________________________________________________________
00037 TMethodCall::TMethodCall()
00038 {
00039    // Default TMethodCall ctor. Use Init() to initialize the method call
00040    // environment.
00041 
00042    fFunc     = 0;
00043    fOffset   = 0;
00044    fClass    = 0;
00045    fMetPtr   = 0;
00046    fMethod   = "";
00047    fParams   = "";
00048    fProto    = "";
00049    fDtorOnly = kFALSE;
00050    fRetType  = kNone;
00051 }
00052 
00053 //______________________________________________________________________________
00054 TMethodCall::TMethodCall(TClass *cl, const char *method, const char *params)
00055 {
00056    // Create a method invocation environment for a specific class, method and
00057    // parameters. The parameter string has the form: "\"aap\", 3, 4.35".
00058    // To execute the method call TMethodCall::Execute(object,...).
00059    // This two step method is much more efficient than calling for
00060    // every invocation TInterpreter::Execute(...).
00061 
00062    fFunc = 0;
00063 
00064    Init(cl, method, params);
00065 }
00066 
00067 //______________________________________________________________________________
00068 TMethodCall::TMethodCall(const char *function, const char *params)
00069 {
00070    // Create a global function invocation environment. The parameter
00071    // string has the form: "\"aap\", 3, 4,35". To execute the
00072    // function call TMethodCall::Execute(...).
00073    // This two step method is much more efficient than calling for
00074    // every invocation TInterpreter::Execute(...).
00075 
00076    fFunc = 0;
00077 
00078    Init(function, params);
00079 }
00080 
00081 //______________________________________________________________________________
00082 TMethodCall::TMethodCall(const TMethodCall &orig) : TObject(orig)
00083 {
00084    // Copy ctor.
00085 
00086    fFunc     = orig.fFunc ? gCint->CallFunc_FactoryCopy(orig.fFunc) : 0;
00087    fOffset   = orig.fOffset;
00088    fClass    = orig.fClass;
00089    fMethod   = orig.fMethod;
00090    fParams   = orig.fParams;
00091    fProto    = orig.fProto;
00092    fDtorOnly = orig.fDtorOnly;
00093    fRetType  = orig.fRetType;
00094 
00095    fMetPtr = 0;
00096 }
00097 
00098 //______________________________________________________________________________
00099 TMethodCall &TMethodCall::operator=(const TMethodCall &rhs)
00100 {
00101    // Assignement operator.
00102 
00103    if (this != &rhs) {
00104       gCint->CallFunc_Delete(fFunc);
00105       fFunc     = rhs.fFunc ? gCint->CallFunc_FactoryCopy(rhs.fFunc) : 0;
00106       fOffset   = rhs.fOffset;
00107       fClass    = rhs.fClass;
00108       fMethod   = rhs.fMethod;
00109       fParams   = rhs.fParams;
00110       fProto    = rhs.fProto;
00111       fDtorOnly = rhs.fDtorOnly;
00112       fRetType  = rhs.fRetType;
00113 
00114       delete fMetPtr;
00115       fMetPtr = 0;
00116    }
00117 
00118    return *this;
00119 }
00120 
00121 //______________________________________________________________________________
00122 TMethodCall::~TMethodCall()
00123 {
00124    // TMethodCall dtor.
00125 
00126    gCint->CallFunc_Delete(fFunc);
00127    delete fMetPtr;
00128 }
00129 
00130 //______________________________________________________________________________
00131 TObject *TMethodCall::Clone(const char *) const
00132 {
00133    // Return an exact copy of this object.
00134 
00135    TObject *newobj = new TMethodCall(*this);
00136    return newobj;
00137 }
00138 
00139 //______________________________________________________________________________
00140 static TClass *R__FindScope(const char *function, UInt_t &pos, ClassInfo_t *cinfo)
00141 {
00142    // Helper function to find the scope associated with a qualified
00143    // function name
00144 
00145    if (function) {
00146       UInt_t nested = 0;
00147       for(int i=strlen(function); i>=0; --i) {
00148          switch(function[i]) {
00149             case '<': --nested; break;
00150             case '>': ++nested; break;
00151             case ':':
00152                if (nested==0) {
00153                   if (i>2 && function[i-1]==':') {
00154                      TString scope(function);
00155                      scope[i-1] = 0;
00156                      pos = i+1;
00157                      TClass *cl = TClass::GetClass(scope);
00158                      if (!cl) gCint->ClassInfo_Init(cinfo, scope);
00159                      return cl;
00160                   }
00161                }
00162                break;
00163          }
00164       }
00165    }
00166    return 0;
00167 }
00168 
00169 //______________________________________________________________________________
00170 void TMethodCall::Init(TClass *cl, const char *method, const char *params)
00171 {
00172    // Initialize the method invocation environment. Necessary input
00173    // information: the class, method name and the parameter string
00174    // of the form "\"aap\", 3, 4.35".
00175    // To execute the method call TMethodCall::Execute(object,...).
00176    // This two step method is much more efficient than calling for
00177    // every invocation TInterpreter::Execute(...).
00178 
00179    ClassInfo_t *cinfo = gCint->ClassInfo_Factory();
00180    if (!cl) {
00181       UInt_t pos = 0;
00182       cl = R__FindScope(method,pos,cinfo);
00183       method = method+pos;
00184    }
00185    InitImplementation(method,params,0,cl,cinfo);
00186    gCint->ClassInfo_Delete(cinfo);
00187 }
00188 
00189 //______________________________________________________________________________
00190 void TMethodCall::Init(const char *function, const char *params)
00191 {
00192    // Initialize the function invocation environment. Necessary input
00193    // information: the function name and the parameter string of
00194    // the form "\"aap\", 3, 4.35".
00195    // To execute the method call TMethodCall::Execute(...).
00196    // This two step method is much more efficient than calling for
00197    // every invocation TInterpreter::Execute(...).
00198 
00199    UInt_t pos = 0;
00200    ClassInfo_t *cinfo = gCint->ClassInfo_Factory();
00201    TClass *cl = R__FindScope(function,pos,cinfo);
00202    InitImplementation(function+pos, params, 0, cl, cinfo);
00203    gCint->ClassInfo_Delete(cinfo);
00204 }
00205 
00206 //______________________________________________________________________________
00207 void TMethodCall::InitImplementation(const char *methodname, const char *params,
00208                                      const char *proto, TClass *cl,
00209                                      const ClassInfo_t *cinfo) 
00210 {
00211    // This function implements Init and InitWithPrototype.
00212 
00213    // 'methodname' should NOT have any scope information in it.  The scope
00214    // information should be passed via the TClass or CINT ClassInfo.
00215 
00216    if (!fFunc)
00217       fFunc = gCint->CallFunc_Factory();
00218    else
00219       gCint->CallFunc_Init(fFunc);
00220 
00221    fClass    = cl;
00222    fMetPtr   = 0;
00223    fMethod   = methodname;
00224    fParams   = params ? params : "";
00225    fProto    = proto ? proto : "";
00226    fDtorOnly = kFALSE;
00227    fRetType  = kNone;
00228 
00229    ClassInfo_t *scope = 0;
00230    ClassInfo_t *global = gCint->ClassInfo_Factory();
00231    if (cl) scope = (ClassInfo_t*)cl->GetClassInfo();
00232    else    scope = (ClassInfo_t*)cinfo;
00233   
00234    if (!scope) return;
00235 
00236    R__LOCKGUARD2(gCINTMutex);
00237    if (params && params[0]) {
00238       gCint->CallFunc_SetFunc(fFunc, scope, (char *)methodname, (char *)params, &fOffset);
00239    } else if (proto && proto[0]) {
00240       gCint->CallFunc_SetFuncProto(fFunc, scope, (char *)methodname, (char *)proto, &fOffset);
00241    } else {
00242       // No parameters
00243       gCint->CallFunc_SetFunc(fFunc, scope, (char *)methodname, "", &fOffset);
00244    }
00245    
00246    gCint->ClassInfo_Delete(global);
00247 }
00248 
00249 //______________________________________________________________________________
00250 void TMethodCall::InitWithPrototype(TClass *cl, const char *method, const char *proto)
00251 {
00252    // Initialize the method invocation environment. Necessary input
00253    // information: the class, method name and the prototype string of
00254    // the form: "char*,int,float".
00255    // To execute the method call TMethodCall::Execute(object,...).
00256    // This two step method is much more efficient than calling for
00257    // every invocation TInterpreter::Execute(...).
00258 
00259    ClassInfo_t *cinfo = gCint->ClassInfo_Factory();
00260    if (!cl) {
00261       UInt_t pos = 0;
00262       cl = R__FindScope(method,pos,cinfo);
00263       method = method+pos;
00264    }
00265    InitImplementation(method, 0, proto, cl, cinfo);
00266    gCint->ClassInfo_Delete(cinfo);
00267 }
00268 
00269 //______________________________________________________________________________
00270 void TMethodCall::InitWithPrototype(const char *function, const char *proto)
00271 {
00272    // Initialize the function invocation environment. Necessary input
00273    // information: the function name and the prototype string of
00274    // the form: "char*,int,float".
00275    // To execute the method call TMethodCall::Execute(...).
00276    // This two step method is much more efficient than calling for
00277    // every invocation TInterpreter::Execute(...).
00278 
00279    UInt_t pos = 0;
00280    ClassInfo_t *cinfo = gCint->ClassInfo_Factory();
00281    TClass *cl = R__FindScope(function,pos,cinfo);
00282    InitImplementation(function+pos, 0, proto, cl, cinfo);
00283    gCint->ClassInfo_Delete(cinfo);
00284 }
00285 
00286 //______________________________________________________________________________
00287 Bool_t TMethodCall::IsValid() const
00288 {
00289    // Return true if the method call has been properly initialized and is
00290    // usable.
00291 
00292    return fFunc ? gCint->CallFunc_IsValid(fFunc) : kFALSE;
00293 }
00294 
00295 //______________________________________________________________________________
00296 TFunction *TMethodCall::GetMethod()
00297 {
00298    // Returns the TMethod describing the method to be executed. This takes
00299    // all overriding and overloading into account (call TClass::GetMethod()).
00300    // Since finding the method is expensive the result is cached.
00301 
00302    // Since the object in the list of global function are often deleted
00303    // we need to copy them.
00304 
00305    if (!fMetPtr) {
00306       if (fClass) {
00307          if (fProto == "") {
00308             fMetPtr = fClass->GetMethod(fMethod.Data(), fParams.Data());
00309          } else {
00310             fMetPtr = fClass->GetMethodWithPrototype(fMethod.Data(), fProto.Data());
00311          }
00312          TMethod *met = dynamic_cast<TMethod*>(fMetPtr);
00313          if (met) fMetPtr = new TMethod(*met);
00314       } else {
00315          if (fProto == "")
00316             fMetPtr = gROOT->GetGlobalFunction(fMethod.Data(), fParams.Data(), kTRUE);
00317          else
00318             fMetPtr = gROOT->GetGlobalFunctionWithPrototype(fMethod.Data(), fProto.Data(), kTRUE);
00319          if (fMetPtr) fMetPtr = new TFunction(*fMetPtr);
00320       }
00321    }
00322 
00323    return fMetPtr;
00324 }
00325 
00326 //______________________________________________________________________________
00327 void TMethodCall::Execute(void *object)
00328 {
00329    // Execute the method (with preset arguments) for the specified object.
00330 
00331    if (!fFunc) return;
00332    
00333    R__LOCKGUARD2(gCINTMutex);
00334    void *address = 0;
00335    if (object) address = (void*)((Long_t)object + fOffset);
00336    gCint->SetTempLevel(1);
00337    if (fDtorOnly) {
00338       Long_t saveglobalvar = gCint->Getgvp();
00339       gCint->Setgvp((Long_t)address);
00340       gCint->CallFunc_Exec(fFunc,address);
00341       gCint->Setgvp(saveglobalvar);
00342    } else
00343       gCint->CallFunc_Exec(fFunc,address);
00344    gCint->SetTempLevel(-1);
00345 }
00346 
00347 //______________________________________________________________________________
00348 void TMethodCall::Execute(void *object, const char *params)
00349 {
00350    // Execute the method for the specified object and argument values.
00351 
00352    if (!fFunc) return;
00353    
00354    R__LOCKGUARD2(gCINTMutex);
00355    gCint->CallFunc_SetArgs(fFunc, (char *)params);
00356 
00357    void *address = 0;
00358    if (object) address = (void*)((Long_t)object + fOffset);
00359    gCint->SetTempLevel(1);
00360    gCint->CallFunc_Exec(fFunc,address);
00361    gCint->SetTempLevel(-1);
00362 }
00363 
00364 //______________________________________________________________________________
00365 void TMethodCall::Execute(void *object, Long_t &retLong)
00366 {
00367    // Execute the method (with preset arguments) for the specified object.
00368 
00369    if (!fFunc) return;
00370    
00371    R__LOCKGUARD2(gCINTMutex);
00372    void *address = 0;
00373    if (object) address = (void*)((Long_t)object + fOffset);
00374    gCint->SetTempLevel(1);
00375    retLong = gCint->CallFunc_ExecInt(fFunc,address);
00376    gCint->SetTempLevel(-1);
00377 }
00378 
00379 //______________________________________________________________________________
00380 void TMethodCall::Execute(void *object, const char *params, Long_t &retLong)
00381 {
00382    // Execute the method for the specified object and argument values.
00383 
00384    if (!fFunc) return;
00385    
00386    R__LOCKGUARD2(gCINTMutex);
00387    gCint->CallFunc_SetArgs(fFunc, (char *)params);
00388 
00389    void *address = 0;
00390    if (object) address = (void*)((Long_t)object + fOffset);
00391    gCint->SetTempLevel(1);
00392    retLong = gCint->CallFunc_ExecInt(fFunc,address);
00393    gCint->SetTempLevel(-1);
00394 }
00395 
00396 //______________________________________________________________________________
00397 void TMethodCall::Execute(void *object, Double_t &retDouble)
00398 {
00399    // Execute the method (with preset arguments) for the specified object.
00400 
00401    if (!fFunc) return;
00402    
00403    R__LOCKGUARD2(gCINTMutex);
00404    void *address = 0;
00405    if (object) address = (void*)((Long_t)object + fOffset);
00406    gCint->SetTempLevel(1);
00407    retDouble = gCint->CallFunc_ExecDouble(fFunc,address);
00408    gCint->SetTempLevel(-1);
00409 }
00410 
00411 //______________________________________________________________________________
00412 void TMethodCall::Execute(void *object, const char *params, Double_t &retDouble)
00413 {
00414    // Execute the method for the specified object and argument values.
00415 
00416    if (!fFunc) return;
00417    
00418    R__LOCKGUARD2(gCINTMutex);
00419    gCint->CallFunc_SetArgs(fFunc, (char *)params);
00420 
00421    void *address = 0;
00422    if (object) address = (void*)((Long_t)object + fOffset);
00423    gCint->SetTempLevel(1);
00424    retDouble = gCint->CallFunc_ExecDouble(fFunc,address);
00425    gCint->SetTempLevel(-1);
00426 }
00427 
00428 //______________________________________________________________________________
00429 void TMethodCall::Execute(void *object, char **retText)
00430 {
00431    // Execute the method (with preset arguments) for the specified object.
00432 
00433    if (!fFunc) return;
00434    
00435    R__LOCKGUARD2(gCINTMutex);
00436    void *address = 0;
00437    if (object) address = (void*)((Long_t)object + fOffset);
00438    gCint->SetTempLevel(1);
00439    *retText =(char*) (gCint->CallFunc_ExecInt(fFunc,address));
00440    gCint->SetTempLevel(-1);
00441 }
00442 
00443 //______________________________________________________________________________
00444 void TMethodCall::Execute(void *object, const char *params, char **retText)
00445 {
00446    // Execute the method for the specified object and argument values.
00447 
00448    if (!fFunc) return;
00449    
00450    R__LOCKGUARD2(gCINTMutex);
00451    gCint->CallFunc_SetArgs(fFunc, (char *)params);
00452 
00453    void *address = 0;
00454    if (object) address = (void*)((Long_t)object + fOffset);
00455    gCint->SetTempLevel(1);
00456    *retText =(char*)(gCint->CallFunc_ExecInt(fFunc,address));
00457    gCint->SetTempLevel(-1);
00458 }
00459 
00460 //______________________________________________________________________________
00461 TMethodCall::EReturnType TMethodCall::ReturnType()
00462 {
00463    // Returns the return type of the method. Either (unsigned) long,
00464    // int, short and char, or float and double or anything else.
00465    // Since finding the return type is expensive the result is cached.
00466 
00467    if ( fRetType == kNone) {
00468       TFunction *func = GetMethod();
00469       if (func == 0) {
00470          fRetType = kOther;
00471          Error("ReturnType","Unknown method");
00472          return kOther;
00473       }
00474 
00475       // count the number of stars in the name.
00476       Int_t nstar = 0;
00477       const char* rettype = func->GetReturnTypeName();
00478       const char* returntype = rettype;
00479       while (*returntype) {
00480          if (*returntype == '*') nstar++;
00481          returntype++;
00482       }
00483 
00484       TypedefInfo_t *atype = gCint->TypedefInfo_Factory();
00485       gCint->TypedefInfo_Init(atype,gCint->TypeName(rettype));
00486       //be careful, below this point rettype cannot be reused (point to a static in TCint)
00487       
00488       const char *name = gCint->TypedefInfo_TrueName(atype);
00489 
00490       Bool_t isEnum = kFALSE;
00491       TypeInfo_t *typed = 0;
00492       if (!strcmp("(unknown)",name)) {
00493          typed = gCint->TypeInfo_Factory();         
00494          gCint->TypeInfo_Init(typed,func->GetReturnTypeName());
00495          name  = gCint->TypeInfo_TrueName(typed);
00496          if (gCint->TypeInfo_Property(typed)&kIsEnum) {
00497             isEnum = kTRUE;
00498          }
00499       }
00500 
00501       if ((nstar==1) &&
00502           (!strcmp("unsigned char", name)        || !strcmp("char", name)         ||
00503            !strcmp("UChar_t", name)              || !strcmp("Char_t", name)       ||
00504            !strcmp("const unsigned char", name)  || !strcmp("const char", name)   ||
00505            !strcmp("const UChar_t", name)        || !strcmp("const Char_t", name) ||
00506            !strcmp("unsigned char*", name)       || !strcmp("char*", name)        ||
00507            !strcmp("UChar_t*", name)             || !strcmp("Char_t*", name)      ||
00508            !strcmp("const unsigned char*", name) || !strcmp("const char*", name)  ||
00509            !strcmp("const UChar_t*", name)       || !strcmp("const Char_t*", name)))
00510          fRetType = kString;
00511       else if (!strcmp("unsigned int", name)   || !strcmp("int", name)      ||
00512                !strcmp("unsigned long", name)  || !strcmp("long", name)     ||
00513                !strcmp("unsigned long long", name) || !strcmp("long long", name) ||
00514                !strcmp("unsigned short", name) || !strcmp("short", name)    ||
00515                !strcmp("unsigned char", name)  || !strcmp("char", name)     ||
00516                !strcmp("UInt_t", name)         || !strcmp("Int_t", name)    ||
00517                !strcmp("ULong_t", name)        || !strcmp("Long_t", name)   ||
00518                !strcmp("ULong64_t", name)      || !strcmp("Long_t64", name) ||
00519                !strcmp("UShort_t", name)       || !strcmp("Short_t", name)  ||
00520                !strcmp("UChar_t", name)        || !strcmp("Char_t", name)   ||
00521                !strcmp("Bool_t", name)         || !strcmp("bool", name)     ||
00522                strstr(name, "enum"))
00523          fRetType = kLong;
00524       else if (!strcmp("float", name)   || !strcmp("double", name)    ||
00525                !strcmp("Float_t", name) || !strcmp("Double_t", name))
00526          fRetType = kDouble;
00527       else if (isEnum)
00528          fRetType = kLong;
00529       else
00530          fRetType = kOther;
00531       gCint->TypeInfo_Delete(typed);
00532       gCint->TypedefInfo_Delete(atype);
00533 
00534    }
00535 
00536    return fRetType;
00537 }
00538 
00539 //______________________________________________________________________________
00540 void TMethodCall::SetParamPtrs(void *paramArr, Int_t nparam)
00541 {
00542    // ParamArr is an array containing the function argument values.
00543    // If nparam = -1 then paramArr must contain values for all function
00544    // arguments, otherwise Nargs-NargsOpt <= nparam <= Nargs, where
00545    // Nargs is the number of all arguments and NargsOpt is the number
00546    // of default arguments.
00547 
00548    if (!fFunc) return;
00549    R__LOCKGUARD2(gCINTMutex);
00550    gCint->CallFunc_SetArgArray(fFunc,(Long_t *)paramArr, nparam);
00551 }
00552 
00553 //______________________________________________________________________________
00554 void TMethodCall::ResetParam()
00555 {
00556    // Reset parameter list. To be used before the first call the SetParam().
00557 
00558    if (!fFunc) return;
00559    gCint->CallFunc_ResetArg(fFunc);
00560 }
00561 
00562 //______________________________________________________________________________
00563 void TMethodCall::SetParam(Long_t l)
00564 {
00565    // Add a long method parameter.
00566 
00567    if (!fFunc) return;
00568    gCint->CallFunc_SetArg(fFunc,l);
00569 }
00570 
00571 //______________________________________________________________________________
00572 void TMethodCall::SetParam(Double_t d)
00573 {
00574    // Add a double method parameter.
00575 
00576    if (!fFunc) return;
00577    gCint->CallFunc_SetArg(fFunc,d);
00578 }
00579 
00580 //______________________________________________________________________________
00581 void TMethodCall::SetParam(Long64_t ll)
00582 {
00583    // Add a long long method parameter.
00584 
00585    if (!fFunc) return;
00586    gCint->CallFunc_SetArg(fFunc,ll);
00587 }
00588 
00589 //______________________________________________________________________________
00590 void TMethodCall::SetParam(ULong64_t ull)
00591 {
00592    // Add a unsigned long long method parameter.
00593 
00594    if (!fFunc) return;   
00595    gCint->CallFunc_SetArg(fFunc,ull);
00596 }

Generated on Tue Jul 5 14:11:55 2011 for ROOT_528-00b_version by  doxygen 1.5.1