Using Root with Visual Studio 2008

Dear Rooters
I have inherited a (pretty complex) code that has been developed for a Windows platform to perform data acquisition. I would like to be able to manage histograms and canvases by adding new code to the existing one. I created a similar program in the past in the context of Qt and QtRoot, but the Visual Studio environment is new to me, so I definitely need examples or tutorials on how to include root canvases. I found a few references to this issue through google, but the information (provided by Axel Neumann) is far from introductory, mostly consisting in replies to very specific questions.

Could you be of any help? I guess out there there must be many other souls like me waiting for input on this issue.

Thanks, Dario

Hi Dario,

see: How to Embed a TCanvas in External Applications and the 5.10/00 Release Notes at “Embedding ROOT in External Applications”

Cheers, Bertrand.

Thanks for the info, but my question has a much larger scope: I need a somewhat detailed tutorial not only on C++ coding (such as your link explains) but also on how to modify the build environment of a Microsoft project in order to include references to the root dynamic libraries and all the steps needed to produce a working code (the equivalent of a Makefile on Windows). I knew how to do this in the framework of Qt but I have no familiarity with Visual Studio, and such a tutorial would save me a LONG period of self training (by basically iterating trial and failure attempts).

Thanks for any help (I know that Axel Naumann is an expert on the subject and maybe he can provide valuable hints)

Thanks, Dario

Hi,

OK, then this is a Visual Studio issue, so there are two ways:

  1. Current project solution: From your project properties (by right clicking on your project), in C/C++, add $(ROOTSYS)\include in the “Additional Include Directories” field, then in Linker, add $(ROOTSYS)\lib in the “Additional Library Directories” field
  2. Global solution: Select Options from the Tools menu of Visual Studio, then select “VC++ Directories” in “Projects and Solutions”, and add $(ROOTSYS)\lib to the library files and $(ROOTSYS)\include to the include files

And then, in your project properties, add the ROOT libraries in “Additional Dependencies” (for the Linker)
This should be it.

Cheers, Bertrand.

This was MUCH more helpful. Still, I have problems with very basic issues. After having successfully installed ROOT on windows (I can run it interactively, it’s in [color=#0000BF]c:\root[/color]) I created an empty “Visual C++/CLR/Windows Form Application” in Visual Studio 2008. In the main progam I then just add an

#include "TApplication.h"

statement, just to see if I can successfully compile and resolve the reference to the external include file. The code compiles successfully, but I have an unexpected list of link errors such as:

rootCanvas.obj : warning LNK4248: unresolved typeref token (01000019) for 'TClass'; image may not run

there’s a handful of such LNK4248 errors, and then there’s a longer list of errors such as:

rootCanvas.obj : error LNK2028: unresolved token (0A00000E) "public: virtual void __clrcall TApplicationImp::ShowMembers(class TMemberInspector &)" (?ShowMembers@TApplicationImp@@$$FUAMXAAVTMemberInspector@@@Z) referenced in function "void __clrcall `dynamic initializer for 'const TApplicationImp::`vftable'''(void)" (???__E??_7TApplicationImp@@6B@@@YMXXZ@?A0xf6f2d9e3@@$$FYMXXZ)

This is probably due to the fact that [color=#000080]TApplication.h[/color] includes somewhere inline implementations of code and I did not specify what libraries should contain these compiled implementations (I only specified where the root libraries are in the “[color=#000080]tools/options/Projects and Solutions/VC++ Directories[/color]”). If my suspicion is correct, how am I supposed to specify the library list in Visual Studio (as I would do in Linux with [color=#FF0000][b]root-config --libs[/b][/color]?).

As you suggest in your reply I added the following:



but still this does not specify the list of libraries that must be linked (the -l option in the gnu g++ compiler).

Hope to get further help on this :slight_smile:

Hi,

In the same dialog, under Linker>Input, in the “Additional Dependencies” field, you have to add (manually) the ROOT libraries you want to link with. For example, here are the libraries given by root-config --glibs: libCore.lib libCint.lib libRIO.lib libNet.lib libHist.lib libGraf.lib libGraf3d.lib libGpad.lib libTree.lib libRint.lib libPostscript.lib libMatrix.lib libPhysics.lib libMathCore.lib libThread.lib libGui.lib
It’s what I meant by:[quote]And then, in your project properties, add the ROOT libraries in “Additional Dependencies” (for the Linker)[/quote]Sorry if it was not clear enough
And quoting MSDN Help (you can access the help anytime by pressing F1):

[quote]To add .lib files as linker input in the development environment

  1. Open the project’s Property Pages dialog box. For details, see Setting Visual C++ Project Properties.
  2. Click the Linker folder.
  3. Click the Input property page.
  4. Modify the Additional Dependencies property.
    [/quote]
    Cheers, Bertrand.

This in fact seems to work better: still, I have quite a few unresolved symbols such as

(there’s about 80 of those). I suspect that the order in which I have to declare them in the Link Project Property matters: if this is correct, since I put ALL the libraries I could find, what is the correct order?

More in general: [quote]how can I determine which class belongs to which library?[/quote] (on linux I use nm --demangle piped to a grep)

Thanks, this is really helping me a lot to see the end of tunnel, Dario

Hi Dario,

[quote=“Menasce”]This in fact seems to work better: still, I have quite a few unresolved symbols such as[/quote]This is weird… could you post your full project (in a zip, tar or whatever), so I can see what’s going wrong?

[quote=“Menasce”]I suspect that the order in which I have to declare them in the Link Project Property matters[/quote]No, the order doesn’t matter.

And to find a symbol (e.g. ClassName) in a library (e.g. libname.lib), you can use the “dumpbin” command line utility:

dumpbin /exports libname.lib | find "ClassName" | moreBut you must be in a “Visual Studio Command Prompt” environment. For example, with VS2008:
From the “Start” Windows menu -> “All Programs” -> “Microsoft Visual Studio 2008” -> “Visual Studio Tools” -> “Visual Studio 2008 Command Prompt”

Cheers, Bertrand.

Sure, remember: in order to learn how to insert a canvas, I just created an empty widget, compiled and run. Then I just added a #include "TApplication.h" statement to see if I could resolve symbols correctly. This is all about this mockup project.

You may find the zipped file on lxplus: ~menasce/public/rootCanvas.zip

Thanks for your help, Dario

OK, I see… Sorry, but I missed the fact that you were using CLR/Form. I never used “Visual C++/CLR/Windows Form Application” before, so I’ll need time to see how to use ROOT with Windows Form (if possible at all)… And I’m not going to spend time on it right now. Could you try with a MFC application instead? or do you really need the CLR/Form? What is the format of your data acquisition project?

Cheers, Bertrand.

[color=#FF0000]Ooops[/color], you’re right, I started with the wrong type of project in my self-tutorial. Since the DAQ I inherited appears to be an MFC Application (in particular a Dialog-based one), I re-did the exercise in this new context. Everything is fine (it compiles with the addition of TApplication.h and TH1D.h include file) until I try to instantiate a TH1D histogram:

At that point I get an overload error (did root overload the new operator?!)

I see from google that this appears to be a rather frequent problem, but no post actually quotes the problem solution in the context of root AND VS.

Hope this info is enough for you to provide an answer that doesn’t take you too much time.
Really thanks for the help, Dario

Hi Dario,

Oh yes, I forgot this… It is probably due to the fact that Microsoft is overloading the operator new in debug mode… #-o
So in your generated code, just look for these lines:

#ifdef _DEBUG #define new DEBUG_NEW #endif
and just comment out the #define new DEBUG_NEW line:

#ifdef _DEBUG //#define new DEBUG_NEW #endif
This should fix the problem.
Cheers, Bertrand.

Thanks once more (I already figured that out: it sounds crazy to overload one of the most fundamental functions of C++, it’s like changing the name of Leonardo da Vinci to John Smith da Peoria (Illinois)… :smiley: . Microsoft people are crazy!).
I made some more progress along the lines of your suggested tutorial “[color=#000080]How to Embed a TCanvas in External Applications[/color]”. I created a timer, I placed the idleing functions therein and it compiles successfully. Once I try then to implement the MyWindow::Create() method I have to include a [color=#000080]TCanvas.h[/color] header: at this point I get a very strange compilation error:

1>c:\root\include\tvirtualx.h(184) : error C2059: syntax error : 'constant'

What’s even more interesting, is that by double-clicking on this error line, VS points to the following piece of code, (figure 1), where no apparent reference to a ‘constant’ is present at line 188.


For completeness, I installed root V5.27.06 on my machine.

Please bear with me, but this is frustrating to me as well.
Thanks again, Dario

Hi,

When using ROOT with standard Windows headers, you should add this line:

#include <Windows4Root.h>before any ROOT headers.

Cheers, Bertrand.

Why is the list of steps necessary to run root components on VS not formally detailed in a wiki page? :imp: It think a large community is out there waiting to get a kick to start using root on windows but are refrained from doing so by lack of complete documentation (at least this is the situation with my colleagues here at FNAL).

So far in this process I followed your suggestions and the code compiles and runs but does nothing: I suspect the problem lies in the following statement:

int wid = gVirtualX->AddWindow((ULong_t)getid(), getWidth(), getHeight());
MyWindow, in the VS project, is a [color=#000080]CDialog[/color], which inherits from a [color=#000080]CWin[/color]: therefore I tried to see which methods in a CWin provide info such as Id, width and height. I found none (remember, I’m NOT familiar with VS as I used to be with Qt).

The only thing I could concoct was something like:

Most likely the code does nothing since this->GetDlgCtrlID() returns zero.

Just be sure I tied also a CDialog method, this->GetDefID() which returns something different from zero, but still no canvas shows up on the window.

(I implemented the fCanvas->Update() call in the OnPaint method of my CDialog).

Which CDIalog methods should I use then in the signature of the AddWindow method?

Just to ease things, I placed a zip file with my code in the public area [quote]~menasce/public/rootCanvas_good.zip[/quote] on lxplus.

Thanks once more, Dario

Hi Dario,

OK, I put your modified project in /afs/cern.ch/user/b/bellenot/public/rootCanvas_working.tar.gz
But as a Dialog based project is not really a good idea (you’ll see why when running the application), I also put a MDI example: /afs/cern.ch/user/b/bellenot/public/MFCMDIRoot.tar.gz
Hope this will help.

Cheers, Bertrand.

Thanks (really) for your helpful examples. In the case of the Dialog I was one inch away from the correct solution (I worked all night): the only point I was missing is the [color=#FF0000]m_hWnd[/color] class variable to point to the dialog window (I already had figured out how to fetch width and height exactly how you show in your example).

I think I can now successfully work to improve the DAQ: the reason I started with a Dialog mock-up is because it looks like the DAQ was built on top of a Dialog component which then grew enormously. That Dialog now features several nested tabs, one of which I’m planning to use to paste the canvas with my histograms. It even features 3D interactive graphics based on openGL primitives!.. #-o

In other words, I agree that your second example would be more elegant (my Qt application was designed upon that model), but the complexity of the DAQ I inherited has already taken care of and thoroughly debugge and I do not want to reinvent the wheel, so I guess I will stick with it…

Many thanks!!.

[color=#000080]Just a suggestion[/color]: [color=#FF00BF]these two tar files would be ENORMOUSLY helpful to a large community, why don’t you put a link to them from the HOW TO or FAQ section of ROOT’s documentation?[/color]

Dario

Hi Dario,

[quote=“Menasce”]Just a suggestion: these two tar files would be ENORMOUSLY helpful to a large community, why don’t you put a link to them from the HOW TO or FAQ section of ROOT’s documentation?[/quote]Sure! I will polish them a bit and provide them as startup examples (it was already planned, but postponed for too long…)

Cheers, Bertrand.

Hi Bertran,

Could you please tell me how to access the afs public area? I hope to take a look at the examples:

/afs/cern.ch/user/b/bellenot/public/rootCanvas_working.tar.gz

/afs/cern.ch/user/b/bellenot/public/MFCMDIRoot.tar.gz

Thank you very much.

[quote=“bellenot”]Hi Dario,

OK, I put your modified project in /afs/cern.ch/user/b/bellenot/public/rootCanvas_working.tar.gz
But as a Dialog based project is not really a good idea (you’ll see why when running the application), I also put a MDI example: /afs/cern.ch/user/b/bellenot/public/MFCMDIRoot.tar.gz
Hope this will help.

Cheers, Bertrand.[/quote]

Hi,

You must have an afs account to be able to access files on afs, but anyway, the files are available on the web: MFCMDIRoot.tar.gz and rootCanvas_working.tar.gz

Cheers, Bertrand.