Introduction

As of Version 2.1 it is possible (though non-trivial) to wrap your own ROOT objects. This wrapping is done in addition to the main ROOT wrappers – an addon if you will.

The following example uses an nmake file to do the job. It starts with two small files (BTagJet.cpp/.h and MuonInBJet.cpp/h) that contains simple C++ classes that derive from TLorentzVector (which, in turn, derives from TObject). Wrapping objects is two steps. First one must build the ROOT library (with rootcint run, etc.) and second one needs to build the wrapper library. In this example, I’m using ROOT’s ACLIC facility to do build the ROOT libraries (two of them). However, one can build them whatever way one likes!

Creating a Wrapper Library

  1. Create a new NMake project in Visual Studio. The build command should be “nmake /F build.mak all”.
  2. Add the .cpp and .h files to this project
  3. Create a build.mak file in the root directory of the project you’ve just created and copy in the the contents at the end of this page, and add it to the project.
  4. Right click on the project and select “build”. This should build the ROOT library dll’s and also the wrapper project.
  5. Add the new project to the solution (called “NTupleWrappers” here).
  6. Right click on the wrappers project, select “Project Dependencies…” and then select “NtupleClasses”.
  7. Hit build!

Do not put the dependent project into source control (NTupleWrappers). However, put the nmake project into source control! Make sure to add the cpp/h files along with the make file! You can, of course, check in everything… I’m just a little leery of checking in auto-generated code!

Known Problems

Some are by-design (!!), and some are bugs that need fixing…

  • Do not modify the options for the wrapper project library! I know, it is tempting! However, that project file is auto-generated by the wrapper making code, so any changes will be overwritten. This is “by-design” for now, I’m afraid.
  • Only a Release configuration of the wrappers is built. This shouldn’t be an issue when building everything else Debug, but I’ve been burned by this in the C++ world enough times to know that one needs to at least keep an eye on this.
  • If one adds a new class to the translation then a new project file is generated – and that means the project has to be re-loaded in Visual Studio. This is a major work-flow interruption. I’d call this a bug, but it will require major work to fix!
  • Some files are left behind in places you might not like to be messy – like the solution directory. Some of them are absolutely necessary – don’t delete them or you’ll be sorry! For example, the GIUD file that allows projects to re-use old GUID’s (if they don’t you’ll loose all your project dependencies).
  • When you check this out clean from source control you’ll have a “bad” solution – a missing project. After the first build it will show up. Ugh. The workaround is to check in the generated project.
  • VC2010 sometimes makes updates to the formatting of the project file – which means that when it is regenerated – even if the content is the same, it might get remade… so you’ll have to reload the project when prompted. Sorry – not sure how to get past this right now in VC2010.

The Make File

The make file for this two object set of DLL’s is pretty simple.

#
# Build the ROOT objects into dll's
#

all: netwrapper

#
# Some Defines to make life simpler
#

SolutionDir = ..\\

ROOT = root -l -b -q
ADDON = "c:\root\NETWrappers\bin\ROOT.NET Addon Library Converter.exe" c:\root\NETWrappers $(SolutionDir)

DLLLibraries = MuonInBJet_cpp.dll BTagJet_cpp.dll

#
# Build the project that translates
#

WrapperProjectName = NTupleWrappers

netwrapper: $(SolutionDir)$(WrapperProjectName)\\$(WrapperProjectName).vcxproj

$(SolutionDir)$(WrapperProjectName)\\$(WrapperProjectName).vcxproj: libraries
$(ADDON) $(WrapperProjectName) $(DLLLibraries)

#
# The root dll's that do the build
#

libraries: $(DLLLibraries)

MuonInBJet_cpp.dll BTagJet_cpp.dll : MuonInBJet.cpp MuonInBJet.h BTagJet.cpp BTagJet.h
$(ROOT) compile.C(\"MuonInBJet.cpp\")
$(ROOT) compile.C(\"BTagJet.cpp\")

A few pointers (that are probably obvious):

  • The two objects need to be built in order as BTagJet reference MuonInBJet.
  • The wrapper generator takes a list of DLL’s as input and generates all classes it can find defined in those DLL’s.

And it uses a tiny compile file to build the DLL’s in ROOT:

void compile(char *fname)
{
    gSystem->CompileMacro(fname, "k");
}

Future

It would be nice to develop some VSIX or similar packages to automate all of this, but I’m not there yet! If someone wants to step in and help, I’m more than happy to work with them (and include them on this project, of course!).

Last edited Jan 2, 2011 at 12:19 AM by gwatts, version 8

Comments

No comments yet.