Hi Andrea,
On Tue, 2007-08-14 at 16:41 +0200, Andrea Massironi wrote:
> Dear Rooters,
> I'd like to execute a Cint script contained in a string inside a file.cpp.
>
> For example:
>
> Proof.cpp
...
> I get
>
> > Warning: Automatic variable a is allocated (tmpfile):1:
>
> > a inside = 10
>
> > a outside = 1
See my last email on the subject - scopes are different! Inside your function, there's an 'a' which has nothing to do with the 'a' implicitly created by CINT in the global scope. The following _script_ illustrates that:
// foo.C
int a = 42; void foo() { int b = 1; gROOT->ProcessLine("b = 2; a = 1; std::cout << a << ',' << b << std::endl;"); std::cout << a << ',' << b << std::endl; a = 10; b = 20; }
Notice, how 'a' is indeed changed by the `ProcessLine', while 'b' isn't since it's local to the function 'foo'. Try for example
Root> .x foo.C Processing foo.C... Warning: Automatic variable b is allocated (tmpfile):1: 1,2 1,1 Root> std::cout << a << ',' << b << std::endl; 10,2
Why, because the 'b' you assign to in the 'ProcessLine' is the global, automatically created 'b', while the 'b' assigned to inside the function 'foo' is local to that function.
This is exactly what you'd expect of C++.
> Is it possible to execute a cint script inside a file?
Yep, simply do
gROOT->Macro(".x foo.C");
(The name 'macro' is unfortunate, since it's really a script - not a macro - that you execute).
In fact, it's rather common to use scripts to configure binary code. Suppose you have a singleton object like in my previous mail:
class Manager { public: Manager& Instance(); void AddTask(Task* task); Int_t Run(); private: Manager(); Manager(const Manager&); Manager& operator=(const Manager&) static Manager* _instance; TList _tasks; };
You also have a small program that uses this singleton to execute some sort of job:
int main(int argc, char** argv) { std::string config("config.C"); if (argc > 1) config = argv[1]; Manager& manager = Manager::Instance(); gROOT->Macro(config.c_str()); return manager.Run();
An example of 'config.C' could be
void config() { Manager& manager = Manager::Instance(); // Create task A, and add it to the manager // Must be created on the heap (via new) as it would otherwise // disappear at the end of the "config" function Task* taskA = new TaskA("a", "A"); manager.Add(taskA); // Create task B and add it to the manager TaskB* taskB = new TaskB("b", "B"); taskB->SetCut(42.); manager.Add(taskB); // Load a task from a user library, create an object, and add it. gSystem->Load("mytask.so"); MyTask* myTask = new MyTask; manager.Add(myTask); // ... and so on }
You can now easily make small changes to cuts, parameters, and so on, simply by editing your script accordingly. As shown above, you can easily plug in new 'task' classes to do specialised stuff. Say, you're playing around with doing tracking in different ways, so you derive a class 'FunnyTrackingTask' from the official 'TrackingTask', load that in dynamically, and use that instead without having to change one single piece of code.
Yours,
-- ___ | Christian Holm Christensen |_| | ------------------------------------------------------------- | | Address: Sankt Hansgade 23, 1. th. Phone: (+45) 35 35 96 91 _| DK-2200 Copenhagen N Cell: (+45) 24 61 85 91 _| Denmark Office: (+45) 353 25 404 ____| Email: cholm_at_nbi.dk Web: www.nbi.dk/~cholm | |Received on Tue Aug 14 2007 - 19:39:26 CEST
This archive was generated by hypermail 2.2.0 : Wed Aug 15 2007 - 11:50:02 CEST