How to link macros to a library in Windows?

Hello,

I have a bunch of commonly used classes that I tried to compile into a library so that I may use them in macros that I compile via the ACliC command-line. So for example I created a libMyCode.dll using a VC10 project, and load it in my rootlogon.C:

gSystem->Load(“libMyCode”);

This works well in the sense that I can open a CINT session and create objects of my custom classes etc. However I’m not sure how I can link to it properly for compiled macros, e.g. when executing:

root myMacro.cc+

I obtain several “LNK2001: unresolved external symbol” errors and am unable to continue. Here I have provided both the libMyCode.dll and its static-linking stub libMyCode.lib (which was generated by VC10 in the same compilation job that produced the dll) in the local directory. The errors involve functions like ShowMembers(), Streamer(), and Class(), which should have been in the dll already as far as I know, because it works fully when on its own…

Is there something that I’m doing wrong, or a step that I’m missing? I must admit that I know way too little about library linking in Windows, and hope somebody can help.

Hopeful,

Sue Ann Koay
sakoay@cern.ch

Hi Sue Ann,

Does doing explicitly:root [] gSystem->Load("libMyCode"); root [] .L myMacro.cc++also fails?

Philippe.

Yes it fails, and with the same errors.

I was trying to read up on dll linking, and it seems like for conventional programs I should have used some means of specifying what symbols I want to export from my dll. Do I need to do this even if I want to static link instead of dynamic link? I presume that ACliC is trying to perform a static link, hence the need for the .lib?

The only way that I’ve been able to get this to work is to compile both a dll and a static library (i.e. the full libMyCode.lib and not just the stub), and make them both available to ACliC. However this method causes a TClassTable::Add warning where it complains that various classes are already in TClassTable. I used to ignore these (out of having no other recourse), but recently and quite painfully found out that they cause crashes in some situations. :frowning:

Stuck,

Sue Ann Koay
sakoay@cern.ch

Hi,

I can not reproduce the problem. I did: cd $ROOTSYS/test root.exe root [] .L Event.cxx+ root [] .L MainEvent.cxx+and then cd $ROOTSYS/test root.exe root [] gSystem->Load("Event_cxx"); root [] .L MainEvent.cxx+And $ROOTSYS/test contains both libEvent.lib and libEvent.dll

[quote]The errors involve functions like ShowMembers(), Streamer(), and Class(), which should have been in the dll already as far as I know, because it works fully when on its own…[/quote]I am guessing is that the real problem is either that the dictionary is not linked in the library.

[quote]The only way that I’ve been able to get this to work is to compile both a dll and a static library (i.e. the full libMyCode.lib and not just the stub), and make them both available to ACliC.[/quote]I am not sure what you mean by making both always to ACLiC. A priori both need to exist and the .lib will be used once the .dll is loaded in ROOT.

Cheers,
Philippe.

Hmm, this sounds like it might be some problem in the way that I configured the dll making. I’m using a Visual C++ project, and in case anything obvious occurs to you, the linker options are:

/OUT:libMyCode.dll /INCREMENTAL:NO /NOLOGO /LIBPATH:"C:\Software\Framework\root\lib" /DLL "libHist.lib" "libCore.lib" "libGpad.lib" "libMathCore.lib" "libRIO.lib" "libGraf.lib" "libCint.lib" "libMinuit2.lib" "libTree.lib" "libPhysics.lib" "libvectorDict.lib" "libTreePlayer.lib" "libThread.lib" "libMatrix.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Release\libMyCode.dll.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /PDB:libMyCode.pdb /SUBSYSTEM:WINDOWS /OPT:NOREF /OPT:ICF /PGD:libMyCode.pgd /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE 

The other piece of info is that I have a LinkDef.h file for my library, which I run rootcint on to get a Dict.cpp and Dict.h file. It is compiled as part of my library though, so I don’t know why the symbols should not be present. Furthermore, I am able to use the classes without any problems in CINT after I load libMyCode.

I meant that I created a static library version of the VC++ project, which creates a .lib file that in principle should have been standalone and not required the .dll to be linked to a program. However this does not happen in practice, and I still have to load the dll in order for the code to be compiled without missing symbol errors.

Hi Sue Ann,

Visual C++ creates the .lib with the exported symbols (e.g. the one starting with __declspec(dllexport) keyword, or the ones specified in a .def file), and then the .lib file is used when linking with your application.
So you must not create a static library going along with your dll! (it is more or less like mixing .so and .a files on Linux).
Could you provide a minimal set of files to play with? It would be faster to help this way than trying to reproduce from scratch.

Cheers, Bertrand.