Search for all the TObject classes defined in a shared library

Hi,

I am looking for a method that returns a list with the name of the classes defined in a rootified library.

I go into root shell load the libraries and try the following

[code]gSystem->Load(“myLibrary.so”); //This is OK

gSystem->ListSymbols(“myLibrary.so”); // Nothing on screen[/code]

but nothing appears on screen,

How can I get information about the library inside root? And more in particular get a list of existing classes inside the library?

Thank you!
Javier

Hi,

at the moment that particular interface is not mature enough.
The problem of knowing at runtime the symbols in a library is rather interesting (I assume you are on Linux, tell me if this is not the case).
I see at least two ways to do this at the moment:

  1. Independent of ROOT: pass through an invocation of nm .
  2. Dependent of ROOT, get the list of autoload keys with the gInterpreter->GetMapfile(). This data structure contains all the names of the selected classes (the ones with dictionaries) and the library which contains them. The information is filled starting from rootmap files.

Cheers,
D

Hi,

sorry, I did not have time up to know to do some checks. Thanks for your answer.

Yes, I am using linux. Yes, I though about the invokation through popen of nm as a last option.

I have been trying to get a list with the class names from gInterpreter->GetMapFile(), but I need further investigation.

For example with TClass I can instantiate a class using its name

TClass* c = TClass::GetClass("myDerivedClass"); myBaseClass* mmc = (myBaseClass*) c->New();

Then, somehow TClass must know myDerivedClass name or check it somewhere.

There is not method where I can get the names directly?

As for example something like TClass::GetClassList();

Thanks,
J

Hi,

indeed when invoking TClass::GetClass you are interrogating the ROOT type system. This returns to you the ROOT representation of classes (and namespaces). If the class has a dictionary, you will be able to invoke the “new” method as you did. This is what we use in the IO for example in order to create in memory an “empty” object to be then filled with the persistified information in the TFiles and alike.

The list you are looking for does not exist and for a good reason: ROOT relies massively on dynamic library loading which happens lazily. You can start a very simple executable/macro and at Runtime decide its behaviour loading all and only the libraries you need. This is how all big software setups, at LHC and elsewhere work: run the same executable(s) and configure it at runtime to perform some operation on the data (e.g. Reconstruction, Simulation, analysis filtering).

Now, apart from the “nm -C” invocation, I think the interrogation of the autoload keys via the mapfile is a very good way of getting the list of classes you can call TClass::New for.

Cheers,
D

+1 on Danilo’s suggestion of using gInterpreter->GetMapfile(). Try it - it’s exactly what you need :slight_smile:

Axel.

Hi,

actually I would need a more concrete example to understand how to use

I do

[code]gSystem->Load(“myROOTLibrary.so”);

gInterpreter->GetMapfile()->Print();[/code]

but I do not see any trace of the classes I have inside myROOTLibrary.so

thanks

This will get you started:

auto mf = gInterpreter->GetMapfile();
auto ht = mf->GetTable();

for (auto p : *ht) {
  auto key = p->GetName();
  cout << key << " " << mf->GetValue(key,"") << endl;
  }

Cheers,
Danilo

Hi again,

I put the code you gave me in test.C, I load it in root as a macro. .L test.C and launch it but I get some error.

Error: Symbol p is not defined in current scope test.C:9: Error: Failed to evaluate p->GetName() Warning: Automatic variable key is allocated test.C:9: Error: Undeclared variable key test.C:9: *** Interpreter error recovered ***

Sorry, FOR loops in C++11 are new for me. I have seen few examples on the web and I cannot find where is the error.

Thanks!

Hi,

modern C++ syntax is supported only by the ROOT 6 series.
If you are on ROOT5, you’ll have to adapt it to old style looping.

Cheers,
D

Ok, that explains the error. I am in ROOT 5. #-o

I use the following code. Since TString is a class that is in ROOT, I would expect to see it printed out with the following code. But it is not the case.

[code]Int_t Test( )
{

auto mf = gInterpreter->GetMapfile();
auto ht = mf->GetTable();

for ( int n = 0; n < ht->GetEntries(); n++ ) {

    TString name = ht->At(n)->GetName();
    TString value( mf->GetValue( name, "" ) );

    if( value.Contains("TString" )  )
        cout << "I found it!!" << endl;
}

}[/code]

It seems to me that the right class I should use for what I need is TClassTable.

I just do TClassTable::PrintTable() and it seems to print out all the classes that were added to the dictionary.

[quote] Since TString is a class that is in ROOT,[/quote]Yes, but it is part of libCore which does need a rootmap file …

[quote]I just do TClassTable::PrintTable() and it seems to print out all the classes that were added to the dictionary.
[/quote]
Yes, it does list of all the classes for all the libraries that have been loaded. However you can not select the class coming from a particular library.

Cheers,
Philippe.