Inheriting Root classes to add functionality, and the possible use of plugins

I have been tasked with updating our Root installation from 5.28 to the latest version. My problem lies in the fact that many years ago, before my time, developers added a large number of Root files (cxx and some h) into our project and made proprietary changes to them. I’m guessing they just didn’t know how to do this otherwise. Many of these files can simply be removed from the project by inheriting from the associated Root class and overriding the necessary functions. But there are a few classes that are more difficult, since they are instantiated within Root itself, which would require us to inherit many more Root files than were added into the project to being with.

In perusing the documentation I saw references to plugins. It seems that these can be used to do what I am talking about, to be made to take the place of another class (from which it is derived) that is instantiated inside of Root itself. My question is multiple, since I don’t seem to be able to find any real documentation on how to implement a plugin:

  1. Am I correct in my assessment that this is the best way to enhance the more core (internally used) Root classes whose implementations are out of reach of the application code?
  2. If so, how do I find a list of classes that can be replaced with a plugin in this way? Would that be only those files for folder entries currently found in ./etc/plugins?
  3. Where could I find documentation as to how to implement and use a Root plugin?

My understanding from going through the source, and the files found in the etc/plugins folder, as well as by looking at the etc/system.rootrc config file, is that I should create a DLL which defines the inherited class, and then add a new plugin .C file like those found in folders in the ./etc/plugins folder, eg: ./etc/plugins/TVirtualHistPainter/P010_THistPainter.C whose content is as follows:

void P010_THistPainter()
gPluginMgr->AddHandler(“TVirtualHistPainter”, “*”, “THistPainter”,
“HistPainter”, “THistPainter()”);

Also, for call this I don’t fully understand the parameters. The first parameter is the base class. I believe that the third parameter is the name of the class that I am trying to override, and the fourth parameter is the one I’m overriding it with. Of course the fifth parameter is the constructor. But I’m not sure what the regexp is used for as second parameter. Some use “*”, and others use a caret like “^root:” which seems an unrelated naming. Is there a particular thing that the regexp is being used for?

So if I wrote a class called MyNewHistPainter to override THistPainter, I would assume I would want to:

  1. create a new file in the ./etc/plugins/TVirtualHistPainter folder called P020_THistPainter()
  2. Change the call above to:

gPluginMgr->AddHandler(“TVirtualHistPainter”, “*”, THistPainter", “MyNewHistPainter”, “MyNewHistPainter()”);
Would this be correct?

Thanks for any help.

@Axel I am not sure whom to ping here, so I will try to ask your suggestion or comment? Thank you in advance!

Plugins are “just” a way to move a link dependency to runtime: instead of exposing TFoo to a library, it can instantiate a TFoo through the plugin manager: it knows that the object returned has a given base class it knows, but it doesn’t need to know / depend on the actual implementation of TFoo or its library. Examples are the GUI system, or the extensible handling of "xyz://" file URIs (where TFile matches that URI protocol with the plugin regex), or the one you mention, THistPainter, where histograms need to be able to paint but shouldn’t depend on the graphics system.

In your case, classes with an identical name would have different interfaces, for ROOT and your extensions. That sounds dangerous - ROOT uses some of its classes itself, and we might end up with such a class being replaced. But maybe I’m misunderstanding what you propose.

What I’d recommend is to move these replacement classes into their own namespace. It’s still evil (people will be doing using namespace ABC and then there’s a clash between ROOT’s and yours) but it’s less evil than replacing a class in a shared library with another class with the same name. Could that work?

If you’re going to rename the class anyway, then changing the plugins will only work for classes that are pulled in through the plugin system. As an example, people can do TFile::Open("gfal://...") or new TGFALFile(...), i.e. the plugin path isn’t exclusive. It would depend which classes we’re talking about exactly.