Adding class instance at runtime

Is it possible to do such a thing (and if yes, how?):
[ol]
[li] I have some custom classes written with a root dictionary, i.e. I can use these classes from within cint.[/li]
[li] I have a standalone application which wants to instantiate one of these custom classes at runtime by only having its name (it is easy to check if the class is accessible via TClass::GetDict(“class-name”).[/li][/ol]
Obviously cint can do it so there must be a way to instantiate such a class, but I couldn’t find any hint in the docu. Could you please tell me how to do such a thing.

Example

TClass *cl = TClass::GetClass("TLine"); //or whatever you like TLine *line = (TLine*)cl->New(); line->Dump();
Rene

Thanks’ for the prompt answer, but this is only partially solving the problem: in your example you already know at compilation time that you want to use TLine, what if this is not known.

The idea behind this question is the following: we do have a fitting framework and it would be usefull to have a plugin mechanism for yet unkown functions. If one could implement each function in a class with a functor, the framework would be very flexible. The problem is thus that the class name is not known at compilation time, and hence your approach is not working. I guess also cint does not handle it as you have described it.

Andreas

Hi Andreas,

well, Rene left the exact implementation for your case as an exercise to the reader :slight_smile: Of course you can do:void* CreateMe(const char* what) { return TClass::GetClass(what)->New(); }Now I leave the proper protections (is “what” valid? Did GetClass() find anything? etc) as an exercise to the reader.

Cheers, Axel.

Hi Alex,

it looks like that I am missing some crucial knowledge and I hope you can fill in the gap. If I am doing as you have described it, I will get a pointer to a void object. How do I access now methods of the object. If I could explicitly cast it, it would be trivial but here??

Assume my class is named TUserFcn and has a method of the form

TUserFcn::Eval(Double_t t, const std::vector<Double_t> &param) const;

If I first do something like

void *obj = TClass::GetClass("TUserFcn")->New();

I have (in principle) the object I need but how do I access Eval without explicit casting? I first thought that by using TMethodCall I will be able to access the above Eval method, but it looks like this is not possible since I cannot use TMethodCall::Execute for such a method since it only handles explicity parameters which also needed to be translated into a string (am I right?).

Any concrete hints?

Andreas

Hi,

just stay at the interpreter level. You can dolong result = gROOT->ProcessLine(Form("((TUserFcn*)%p)->Eval(%g, *(const std::vector<Double_t>*)%p)", obj, &param)
That way you pass the object and the parameters from the compiled to the interpreted level. The returned long is a pointer to the object is an object is returned, or the return value cast to a long otherwise. If Eval() returns a double (I’d suspect so :slight_smile: then just set it within the Form() call, i.e. prepend “(double)%p =” and pass a &ret (for ret declared as double) in Form’s parameter list. Let me know if you need a more explicit code example. Check TROOT::ProcessLine()'s doc; it allows you to test for errors during the execution of Eval().

Cheers, Axel.

Hi Alex,

thanks for that tip, this works, though I still have a little problem: calling the method via Interpreter is generating an output string writting on stdout. This is tremendously slowing down calls, especially if they are repetitive. Is there any way to suppress this output, meaning that just the function is called without writting anything to stdout?

Andreas

Hi,

add a semicolon at the end of the call, i.e. “…Eval(…);”.

Cheers, Axel.

Thanks a lot Axel!

I made a quick comparison between directly compiled and interpreted calls, i.e. calling the both several thousend times and measuring the time for computation. The result is a ratio of roughly 1:5000 if the computation in the method is trivial (I used a 2nd order polynom for Eval)

Cheers, Andreas

Hi Andreas,

yes, compared to doing nothing an interpreted call is pretty expensive :slight_smile: An alternative would be to define the base class of the object that you call Eval() on (let’s call it EvalBase::Eval()) within your compiled program, and make the Eval() function virtual. Then you could simply create a new object containing the actual Eval() function to call via TClass::New(), assign the returned value to a EvalBase* ptr, and call Eval() on that: EvalBase* ebobj=(EvalBase*)obj; ebobj->Eval(t, param);
That is much faster, especially if you can reduce the number of calls to TClass::New(), i.e. re-use the object.

Cheers, Axel.

Hi Axel,

brilliant idea. Should have thought about it myself :blush:. Thanks for all the help :laughing:

Andreas