Re:

From: Christian Holm Christensen <cholm_at_nbi.dk>
Date: Wed, 15 Aug 2007 12:05:51 +0200


Hi Axel,

On Tue, 2007-08-14 at 17:42 +0200, Axel Naumann wrote:
> Hi Andrea,
>
> yes, but the same scoping rules apply: the PrcessLine() script does not
> know about Proof()'s int a. Instead, pass it as into the called script as
>
> TString inst = Form("int *a=0x%x; std::cout << \"a inside = \" << *a <<
> std::endl;", &a;
> gROOT->ProcessLine(inst);

Although quite correct do-able, I'd strongly recommend against such practises. Although CINT can easily write a value to some address in memory, there's no guaranty that it will do so correctly. Suppose, that 'a' is some complex object (not excluding POD) - since the exact layout in memory of a complex object is not necessarily predictable nor known to CINT, it could happen that CINT would overwrite memory with invalid data. If you really need to change an variable in the global interpreter scope, you should make that a true global variable.

I'm sure that ROOT/CINT internally uses similar tricks as the one proposed by Axel, which, although questionable, is OK, because the CINT/ROOT developers 'known' their platform(s) pretty well.

Note, that the global interpreter scope has no parallel in real C++, in that you cannot have executable statements outside of function or member function scope. That is,

  // Begin file
  #include <iostream>
  std::cout << "Hello, World!" << std::endl;   // End file

is _not_ a valid C++ program. C++ is a _declarative_ language - a program consists of one or more declarations, and some special declarations (functions and member functions) can contain executable (or imperative) code. This is typical of most modern _programming_ languages: Java, C, C# (God forbid), and so on. Scripting languages, and older languages like Fortran77, are not declarative,

  Fortran77                       | SH                  | Python
  --------------------------------+---------------------+---------------------
  C Begin file                    | #!/bin/sh           | # Start file 
        WRITE(*,*) 'Hello, World' | echo "Hello, world" | print "Hello, World"
  C End file                      | # end file          | # End file

are all valid programs/scripts. Finally, one should contrast all these languages to functional languages, like SML and Lisp, where everything is a function, and side-effects (like printing to screen) is frowned upon. The fact that C++ is declarative is why some people believe that CINT is a futile effort, although it is bloody convenient to be able to write interpreted and executable code in the same language.

That said, it is very likely that, if you need global interpreter variable, that there's something dodgy in your design. The cleanest solution, by far, and recommended by most books on the subject, will be to make singletons. In fact, ROOT should implement some sort of singleton manager for most of it's global variables, like gROOT, gPad, gApplication, gStyle, and so on. First of all, it makes it far easier to make the code thread-safe. Secondly, it makes a cleaner design, which in turn makes it easier to use the ROOT libraries.

So, please try _not_ to use the hack Axel proposed. Instead, make a singleton manager or make the variable truly global in the interpreter scope.

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 Wed Aug 15 2007 - 12:05:59 CEST

This archive was generated by hypermail 2.2.0 : Wed Aug 15 2007 - 17:50:02 CEST