Issues trying to run a macro that "imports/includes" a different file

I have the main macro Analyze.C that looks like:

#include "DataTable.h"
void Analyze() {
    gROOT->Reset();
    DataTable dt = new DataTable(blah);
    //creates a .root file & writes two TTrees into the root file
    //some calculations using DataTable (e.g. dt.dLookUp(d) where d is a doulbe) & TMath
    //adds a branch to each TTree in the file
}

and I have DataTable.h and DataTable.cpp that defines the class DataTable & its relevant methods.

However, when I run .x Analyze.C on interactive root, I get errors like:

IncrementalExecutor::executeFunction: symbol ‘_ZN7DataTable7dLookUpEd’ unresolved while linking [cling interface function]!
You are probably missing the definition of DataTable::dLookUp(double)
Maybe you need to load the corresponding shared library?
IncrementalExecutor::executeFunction: symbol ‘_ZN7DataTableC1ESs’ unresolved while linking [cling interface function]!
You are probably missing the definition of DataTable::DataTable(std::string)
Maybe you need to load the corresponding shared library?

So, it seems that interpreter does not “include” DataTable.h and therefore is not aware of what the DataTable constructor (using one string parameter) is or its method “dLookUp” is.

Here is the weird thing: if I try the same thing AGAIN immediately (literally, up arrow and then enter), the macro starts running without any error about the DataTable class. However, without doing the calculation corresponding to DataTable::dLookUp(double d), it uses d as it is. When it is finished running, the trees & root file are saved properly, but the values in the TTree reflects not the calculated result of DataTable::dLookUp(d) but simply d.

How is this happening, and how should I fix this? How do I import/include a class that is defined in a different .h and .cpp file within a macro?

I have tried:

  1. Get rid of #include “CDTable.h” in the Analyze.C macro file
  2. In root, before running the macro, run .L CDTable.h
  3. Then, run macro .x Analyze.C

I get the exact same error as above and the same weird “run” when I execute the macro again.

  1. Get rid of #include “CDTable.h” in the Analyze.C macro file
  2. In root, before running the macro, run gSystem->Load(“CDTable.h”);
  3. Then, run macro .x Analyze.C

However, I get an error that looks like:

Analyze.C:18:2: error: unknown type
name 'DataTable’
DataTable dt = DataTable(“DataLookUp.dat”);
^
Analyze.C:18:16: error: use of
undeclared identifier 'DataTable’
DataTable dt = DataTable(“DataLookUp.dat”);
^

so it still does not understand what the class DataTable is. If I repeat, I get the same error message (not a weird run where it skips the DataTable related lines)

So, what is wrong here? How can I import/include/load a .h or .cpp file that defines a class, and utilize when executing a macro?

Hi,

I see two solutions:

  1. add: #include “DataTable.cpp” to your macro.
  2. generate a dictionary for DataTable and rely on autoloading.

To perform 2) the steps are:

> genreflex DataTable.h --rootmap dataTable.rootmap
> g++ -shared -fPIC -o libDataTable DataTable_rflx.cpp `root-config --cflags --libs`
> root -l Analyze.C

Danilo

[quote=“dpiparo”]Hi,

I see two solutions:

  1. add: #include “DataTable.cpp” to your macro.
  2. generate a dictionary for DataTable and rely on autoloading.

To perform 2) the steps are:

> genreflex DataTable.h --rootmap dataTable.rootmap
> g++ -shared -fPIC -o libDataTable DataTable_rflx.cpp `root-config --cflags --libs`
> root -l Analyze.C

Danilo[/quote]

When I tried #include “DataTable.cpp” to the fist line of my macro, I got:

*** Break *** segmentation violation

When I try 2: g++ -shared -fPIC -o libDataTable DataTable_rflx.cpp root-config --cflags --libs
gives me an error saying:

g++: error: root-config --cflags --libs: No such file or directory

The reason why your code is not working is that the implementation of the symbols you use in the macro are in the cpp file. What is needed is to make them available to cling.
Now, about the two strategies:

  1. Note that this is equivalent to paste the code of the cpp file inside the macro. Without the original code, not much can be said.
  2. Of course the root environment must be set when calling root related commands.

Wow.

Yes, it was a logic error within my .cpp implementation. After fixing that, #include “DataTable.cpp” at the beginning of the macro.C got the job done.

Thanks a lot about that!

Additional question though: so, for the sake of root macros, is the header file really necessary? Can I just define the class solely within .cpp file and include that?

Hi,

if the class definition is located in the cpp file, either by header inclusion or not, yes.

Cheers,
Danilo

Also please see the ALL CAPS warning in root.cern.ch/doc/master/classTR … fe4eea83f1 - you must not use TROOT::Reset() from a named function.

Cheers, Axel.

D’habitude, j’utilise plutôt root en mode compilé mais 2 application ILAIM et PAD que je dois porter sous linux fonctionne plutôt en mode interprété (CINT)

j’ai une erreur m’indiquant que
TRootEmbeddedCanvas n’est pas défini ( not defined in current scope)

Il existe pourtant bien un fichier de TRootEmbeddedCanvas.h sous /usr/local/root-cern/include/root mais qui ne semble pas être vue

Q1) avez vous rencontré ce genre de problème ?
Q2) en mode CINT , faut –il faire explicitement les include ? ( cela peut-il avoir changé en fonction de la version de root)

NB : Avant le code ILAIM fonctionnait via Cygwin comme émulateur linux

  • Quel OS/compilateur?
  • Quelle version de ROOT?
  • Comment ROOT at-il été installe sur la machine?
  • Est-ce que $ROOTSYS/tutorials/gui/guitest.C fonctionne?

Bonjour,

OS : cat /etc/debian_version : 5.0.3
Version de root 5.34.01-1
installé par l’infogérance
echo $ROOTSYS => /usr/local/root-cern
pas de sous directory tutorial sous cette directory
ci joint résultat de la commande apt-cache show root-cern

Merci d’avance pour ton aide
apt-cache-root-cern.txt (14 KB)

OK, merci pour l’info. Est-ce que tu peux essayer cette macro? embedded.C (1.2 KB)
Et si tu tapes la commande .I dans une session ROOT, il devrait indiquer les includes connus de ROOT. (et au fait, on devrait utiliser l’Anglais sur le forum…)

[bellenot@bbcc7x64 rootdev]$ root -l root [0] .I -I /build/bellenot/bin/root/master/etc -I /build/bellenot/bin/root/master/include -I /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -I /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -I /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -isystem /usr/local/include -isystem /build/bellenot/bin/root/master/etc/cling/lib/clang/3.7.0/include -extern-c-isystem /include -extern-c-isystem /usr/include -I /build/bellenot/git/master/interpreter/cling/include -I /build/bellenot/git/master/interpreter/cling/../../include -I /build/bellenot/bin/root/master/etc/cling -I /build/bellenot/git/master -I /build/bellenot/build/master/include -I /build/bellenot/git/master/graf3d/g3d/inc -I /build/bellenot/git/master/gui/gui/inc -I /build/bellenot/git/master/io/io/inc -I /build/bellenot/git/master/core/base/../textinput/src -I /build/bellenot/build/master/core/base/ -I /build/bellenot/build/master/core/rint/ -I /build/bellenot/build/master/core/thread/ -I /build/bellenot/build/master/io/io/ -I /build/bellenot/git/master/hist/hist/inc -I /build/bellenot/build/master/math/mathcore/ -resource-dir /build/bellenot/bin/root/master/etc/cling/lib/clang/3.7.0 -nostdinc++ root [1]

I tested Embedded.C it is working fine
When I type .i in a root session, I have no error but nothing written

Regards
Thibaut

So ROOT is working fine (and it is capital I BTW). So the problem is in your code, and without looking at it, I’m afraid I can’t really help…

#include "TRootEmbeddedCanvas.h"
is written in the Embedded.C

The ILAIM program (not wriiten by me ), that whose working with Cygwin for XP and the assaciated root version was working
in the program i found there is no explicit include
So maybe in a previus version of root the include was implictly found via an environment variable

As I told you when I type root -l and then .i I get no include information: ist it normal

In another version I found, there are eiher ELF error on dd call or an error symbom MyProgress not defined in current scope

Regards
Thibaut

Thibaut,

[quote=“vinchon-thi”]#include "TRootEmbeddedCanvas.h"
is written in the Embedded.C[/quote]
OK, fine, but if you remove it, it still works (it should). Just try…

Please read carefully: you must type .I (CAPITAL I / I MAJUSCULE) lowercase i does nothing…

That’s another issue…

BTW, what exactly is ILAIM? a macro? an executable built with ROOT? When exactly do you get this error of TRootEmbeddedCanvas not defined in current scope? When running what?

Cheers, Bertrand.

  1. You are write when I remove the include in your Embedded.C exemple it still work
  2. with .I , i get an error mesg : unknow interpreter command .I
  3. As attached file, You will find the file called bay ILAiM .sh which does
    the correct cd
    and then the commande root -x BC501AMainIHMInterface_1.C

Note that with the version of BC501AMainIHMInterface_1.C with the include , the final issue is the ELF error

Regards
Thibaut
BC501AMainInterface_1.C (144 KB)

Well, the first thing I see is this:

[code]#include “…/…/MODULESCOMMUNS9.8.5/ReadDataAcqu2_C.dll”;
#include “…/…/MODULESCOMMUNS9.8.5/FormulaForRebinning_C.dll”;
#include “…/…/MODULESCOMMUNS9.8.5/DoRebinning_C.dll”;
#include “…/…/MODULESCOMMUNS9.8.5/AlgoRebin_C.dll”;
#include “…/…/MODULESCOMMUNS9.8.5/CorrAndAdd2_C.dll”;

[…]

#include “BC501AFunctionsDiscri_C.dll”;
#include “BC501AFiltreBruit_C.dll”;
#include “BC501AFindDiscrimination_C.dll”;
#include “BC501AProjections_C.dll”;
#include “BC501AProjectionSources_C.dll”;
[/code]And this cannot work on Linux, DLL is a Windows specific file format (hence the ELF error)…
So if you really have those dlls, you must first recreate those shared libraries in a linux format (.so) and then modify the source code to include them…

I Finally succeeded to have the GUI ( IHM) opened (by changing Include RIostream.h" by "Riostream.h"
but when I have to make produce result I have error telling for example that function ReadDataAcqu is not in scope (knowing that there is a corresponding ELF error when loading the associated dll

So the main issue is now to understand all these errors in loading dll…

Best regards
Thibaut

Well, I just gave you the solution, right?

Cheers, Bertrand.