TObject::Execute - calling a member method problem

Hi,

my class looks like (see classA.C):

#include <iostream> 

class ClassA:public TObject{
	public:
		ClassA(){}
	   ~ClassA(){}
	void Fun1(const char* msg) { std::cout << "msg = " << msg << std::endl;}
	void Fun2() { std::cout << "no msg ..."<< std::endl;}

   ClassDef(ClassA,1)
};

and I would like to call the the two memeber functions Fun1 and Fun2 if name of the functions and their arguments are given as strings, something like:

root [0] .L classA.C++
Info in <TUnixSystem::ACLiC>: creating shared library /home/jiri/Desktop/test5/./classA_C.so
root [1] ClassA a;
root [2] a.Execute('Fun1','\"mymsg\"');
Error: Can't call ClassA::Execute('Fun1','\"mymsg\"') in current scope (tmpfile):1:
Possible candidates are...
(in ClassA)
public: virtual void TObject::Execute(const char* method,const char* params,Int_t* error=0);
public: virtual void TObject::Execute(TMethod* method,TObjArray* params,Int_t* error=0);
*** Interpreter error recovered ***
root [3] a.Execute('Fun2',"");
Error: Can't call ClassA::Execute('Fun2',"") in current scope (tmpfile):1:
Possible candidates are...
(in ClassA)
public: virtual void TObject::Execute(const char* method,const char* params,Int_t* error=0);
public: virtual void TObject::Execute(TMethod* method,TObjArray* params,Int_t* error=0);
*** Interpreter error recovered ***

unfortunately this doesn’t work as expected…

What do I need to do to get it working?

Thank you in advance,
Jiri

(trunk version of ROOT)
classA.C (244 Bytes)

Hi Jiri,

Try:

root [4] a.Execute("Fun1","\"mymsg\""); msg = mymsg
i.e. " (string delimiter) instead of ’ (char delimiter)

Cheers, Bertrand.

Hi Bertrand,

ohh, stupid mistake #-o, it works without problems! Thank you very much for your fast response.

Cheers,
Jiri

Hi,

BTW, is it possible to somehow catch a return value of a called member fuction (e.g. Fun3 which would return a pointer to a class)?

Thanks,
Jiri

Hi,

You need: TMethodCall *mc = new TMethodCall(ClassA::Class(),"Fun1","\"abc\""); mc->Execute(&a,"\"xyz\"",&ret);

Cheers,
Philippe.

Hi,

thank you for the hint. However, it seems that the return type can be only Long_t, Double_t or char* (see root.cern.ch/root/html/TMethodCa … #TopOfPage). Is there any way how to deal also with the other return types (e.g. with void* which could be then recasted to adequate type)?

Cheers,
Jiri

Hi,

In the example I shown, if the return value is a pointer of any type, it will be stored in ‘ret’ (even though it is a char*). Cheers,
Philippe.

Hi,

then I don’t understand what is the problem with the following example. If I define ClassB:

#include "TString.h"

class ClassB: public TObject{
  public:
	ClassB(){ }
	~ClassB(){}
	TString* Fun(const TString& msg) { return new TString("msg = "+msg); }
    ClassDef(ClassB,1)
};

and do:

[code]
root [0] .L classB.C++
Info in TUnixSystem::ACLiC: creating shared library /home/jiri/Desktop/test5/./classB_C.so
root [1] ClassB b;
root [2] TMethodCall mc = new TMethodCall(ClassB::Class(),“Fun”,"“abc”");
root [3] char
ret;
root [4] mc->Execute(&b,"“xyz”",&ret);

*** Break *** segmentation violation
Generating stack trace…
0x00007f75a016a74f in Cint::G__CallFunc::Execute(void*) + 0xcf from /opt/root/lib/libCint.so
0x00007f75a0ce9d81 in TCint::CallFunc_ExecInt(void*, void*) const + 0x11 from /opt/root/lib/libCore.so
0x00007f75a0d0ec9f in TMethodCall::Execute(void*, char const*, char**) + 0xbf from /opt/root/lib/libCore.so
0x00007f75a104fb14 in from /opt/root/lib/libCore.so
0x00007f75a013a459 in Cint::G__ExceptionWrapper(int ()(G__value, char const*, G__param*, int), G__value*, char*, G__param*, int) + 0x39 from /opt/root/lib/libCint.so
0x00007f75a01dc311 in G__execute_call + 0x61 from /opt/root/lib/libCint.so
0x00007f75a01dc710 in G__call_cppfunc + 0x2a0 from /opt/root/lib/libCint.so
0x00007f75a01bc596 in G__interpret_func + 0x4126 from /opt/root/lib/libCint.so
0x00007f75a01a95db in G__getfunction + 0x171b from /opt/root/lib/libCint.so
0x00007f75a028f643 in G__getstructmem + 0x6b3 from /opt/root/lib/libCint.so
0x00007f75a02877a2 in G__getvariable + 0x1bf2 from /opt/root/lib/libCint.so
0x00007f75a0184ee1 in G__getitem + 0x81 from /opt/root/lib/libCint.so
0x00007f75a018bf98 in G__getexpr + 0x5808 from /opt/root/lib/libCint.so
0x00007f75a020b23a in G__exec_statement + 0x57aa from /opt/root/lib/libCint.so
0x00007f75a0171d91 in from /opt/root/lib/libCint.so
0x00007f75a017329e in G__exec_tempfile_fp + 0xe from /opt/root/lib/libCint.so
0x00007f75a0215f23 in G__process_cmd + 0x14f3 from /opt/root/lib/libCint.so
0x00007f75a0cf11d8 in TCint::ProcessLine(char const*, TInterpreter::EErrorCode*) + 0x4d8 from /opt/root/lib/libCore.so
0x00007f75a0c5fa39 in TApplication::ProcessLine(char const*, bool, int*) + 0x2f9 from /opt/root/lib/libCore.so
0x00007f759fa89328 in TRint::HandleTermInput() + 0x1b8 from /opt/root/lib/libRint.so
0x00007f75a0d238a6 in TUnixSystem::CheckDescriptors() + 0x156 from /opt/root/lib/libCore.so
0x00007f75a0d24cb5 in TUnixSystem::DispatchOneEvent(bool) + 0xd5 from /opt/root/lib/libCore.so
0x00007f75a0cafd16 in TSystem::InnerLoop() + 0x16 from /opt/root/lib/libCore.so
0x00007f75a0cb1ac4 in TSystem::Run() + 0x74 from /opt/root/lib/libCore.so
0x00007f75a0c5deff in TApplication::Run(bool) + 0x1f from /opt/root/lib/libCore.so
0x00007f759fa89c50 in TRint::Run(bool) + 0x180 from /opt/root/lib/libRint.so
0x000000000040117c in main + 0x4c from /opt/root/bin/root.exe
0x00007f759eb76c4d in __libc_start_main + 0xfd from /lib/libc.so.6
0x0000000000401069 in from /opt/root/bin/root.exe[/code]

then I’m not able to get the returned TString* …

What is the problem? I’m lost in the jungle of pointers :confused:

Cheers,
Jiri
classB.C (186 Bytes)

Hi,

The problem is not so much the return value but rather the argument ; TMethodCall does not seem to like the TString reference. The following code:class ClassB: public TObject{ public: ClassB(){ } ~ClassB(){} TString* Fun(const char *msg) { return new TString(TString::Format("msg=%s",msg)); } ClassDef(ClassB,1) };works:root [0] .L mc.C+ root [1] ClassB b; root [2] TMethodCall *mc = new TMethodCall(ClassB::Class(),"Fun","\"abc\""); root [3] mc->IsValid() (const Bool_t)1 root [4] char *ret = 0 root [5] mc->Execute(&b,"\"xyz\"",&ret); root [6] TString *p = (TString*)ret root [7] *p (class TString)"msg=xyz"

Cheers,
Philippe.

Hi,

ok, it is good to know that there is such a limitation with reference to a TString as an argument. Is it supposed to work with another “more complicated” arguments such as pointer to a member function?
E.g. if we define:

[code]
#include
#include “TString.h”

class ClassC: public TObject{
public:
typedef TString* (ClassC::fun1)(const char);
ClassC(){ Fun2(&ClassC::Fun, " called from constructor…");}
~ClassC(){}
TString* Fun(const char msg) { return new TString(TString::Format(“msg=%s”,msg)); }
void Fun2(fun1 fun, const char
msg) { std::cout << "Fun2 … "<< *((this->*fun)(msg)) << std::endl;}
ClassDef(ClassC,1)
};[/code]

and then we try to call the Fun2 which is taking a pointer to a member function, like that:

root [0] .L classC.C+
root [1] ClassC c;
Fun2 ... msg= called from constructor...
root [2] TMethodCall *mc = new TMethodCall(ClassC::Class(),"Fun2","&ClassC::Fun,\"abc\"");
root [3] mc->IsValid()
(const Bool_t)0
root [4] char *ret = 0
root [5] mc->Execute(&c,"&ClassC::Fun,\"abc\"",&ret);
root [6]

then nothing happens, mc is invalid… Is it an another limitation or is there any chance to get it working?

Thank you,
Jiri
classC.C (427 Bytes)

Hi,

CINT does funny things with functions. In particular the address of a function seen by CINT is not the same address as the one seen by the compiler ; CINT sees the address of the wrapper that comes from the dictionary ; as such passing function from the interpreter to the compiler is not simple (see the implementation of TF1 for example).

[quote]root [3] mc->IsValid()
(const Bool_t)0[/quote]indicates that the TMethodCall was not build properly (here it did not find a match for the signature) and thus the Execute with be ‘nop’ and do nothing. To get the signature to match you would need to do:TMethodCall *mc = new TMethodCall(ClassC::Class(),"Fun2","(void*)ClassC::Fun,\"abc\"");however, as explain above, this would result in ‘Fun2’ to receive a pointer to the wrapper function.

So this begs the question :slight_smile:, in which context are you trying to use those construct (maybe there is ‘better’ alternative)?

Cheers,
Philippe.

Hi,

I’m just looking for a way how to call some member functions taking pointers to another (non)member functions as arguments under assumption that the names of the passed functions (and possibly also their arguments) are given by strings (similarlly as in the example with ClassC). Unfortunately, I still don’t see any universal and “user friendly” solution.

Many thanks for your explenation. TMethodCall class definitelly helped me to solve at least some problems.

Cheers,
Jiri

Hi Jiri,

[quote]I’m just looking for a way …[/quote]In which context and to accomplish what higher level task do you want to use these constructs (i.e the ability to call function using their string name)?

Cheers,
Philippe.

Hi Philippe,

main motivation (not the only one!) for all the exercises with the Class{A,B,C} is to somehow call a C++ function which takes a pointer to another function as an argument from pyROOT because pyROOT doesn’t support it right know (it would be the best solution), see How to call function with pointer to a function argument?. So, I got an idea to do it indirectly passing a string (name of a function) instead of a pointer to the function. TObject::Execute and/or TMethodCall looked like good candidates to accomplish the task. I don’t need something as TFormula which can handle complex expresions such as sin(x*(x<0.5 || x>1)).

I would like not to introduce a dictionary - mapping between a pointer to a function and a string or something else because this would require an update whenever I define new function. I want to avoid this manual intervention. Moreover, it would be quite hard to implement this dictionary for member functions belonging to different classes and global non-member functions with different signatures.

Cheers,
Jiri

[quote]main motivation (not the only one!) for all the exercises with the Class{A,B,C} is to somehow call a C++ function which takes a pointer to another function as an argument from pyROOT because pyROOT doesn’t support it right know (it would be the best solution),[/quote]I see and TMethodCall would help you toward that but you also need to properly code the receiving function so that it can handle both function coming from the interpreter and function coming directly from the compiler (see TF1).

I am still pondering to what end (i.e. what feature/high level software) and/or in what context are you needing to have a function which takes a pointer to another function as an argument ?

Cheers,
Philippe.

In a nutshell: I have a litle bit more complicated mathematical function A(x) which includes numerical integrations, differentiations etc. The result of this function A depends on another function B(x) and I need to evaluate the function A for a set of different functions B_i (“different scenarios”) so I need to somehow set a B_i function to the function A and call the function A. I don’t want to introduce a set of A_i functions for each scenario B_i because A is really quite complicated (it would be impossible to maintain the code besides the fact that it would take ages to write the code without introducing one milion of bugs :slight_smile: ).

Do you know any other solution which wouldn’t be based on a pointer to a function as an argument?

Thanks,
Jiri

[quote]Do you know any other solution which wouldn’t be based on a pointer to a function as an argument? [/quote]Yes, you could use functor objects which could thinly or not wrap the B__i function.class MyFunction { public: typedef ... type_of_the_Bi; MyFunction(type_of_the_bi); ... operator()(....) { return fFunction(....); } private: type_of_the_Bi fFunction; };or you could use a virtual interface and implement each Bi as a sub class.

Cheers,
Philippe.