How to import an external lib with ACLiC

Hi there,

I’d like to import an external library into a Root program.

The external lib, say myextlib.cpp, looks like this

void hello() { printf ("Hello World!\n"); return ; } Once compiled with ACLiC (.L myextlib.cpp+), one gets the following library file: “myextlib_cpp.lib” (where .lib is .so, .dll, …).

This library is supposed to be used as follows:

void importlib () { gSystem->Load("myextlib_cpp.lib") ; hello() ; return ; }
Everything goes fine with CINT.x importlib.cppbut I don’t manage to make it work with ACLiC

.L importlib.cpp+(after proper includes: #include <TSystem.h> and #include “myextlib_cpp.lib”)

The error message I get is :

Line too long in G__exec__statement when processing myextlib_cpp.lib:... Missing on of ')' expected at or after line ... Could you please help me on this?

Cheers,
Z

[quote] #include “myextlib_cpp.lib”[/quote]#include expect a text file …
It is possible that you example works if you remove this #include. (However It is more likely to work if you load the .dll version of your library). Also if you only have a static library you can tell ACLiC about it using gSystem->AddLinkedLibs.

Cheers,
Philippe.

[quote]However It is more likely to work if you load the .dll version of your library[/quote]Already tested too (gSystem->Load(“myextlib_cpp.dll”)), in vain :frowning:

[quote]Also if you only have a static library you can tell ACLiC about it using gSystem->AddLinkedLibs[/quote]I don’t have any static version of this library and haven’t found a way to generate one with ACLiC.

Any other clue?
Cheers,
Z

PS: I’ve tried the following “load commands”

gSystem->Load("myextlib_cpp.dll") ; gSystem->Load("myextlib_cpp") ; gSystem->AddLinkedLibs("-L./ -lmyextlib_cpp") ; // UG_5.26, p.94 prior to call ACLiC .L importlib.cpp+and without any include (i.e. with only the hello() statement in importlib()),
in vain :frowning:
I always end up with the same error'hello' was not declared in this scope

[quote]Already tested too (gSystem->Load(“myextlib_cpp.dll”))[/quote]So it sounds like you really do want to usr the result of ACLiC. In which case it is easy:// myexlib.cpp void hello() { printf ("Hello World!\n"); return ; }[code]//importlib.cpp

// The following line could be in a hello.h
void hello();

void importlib ()
{
hello() ;
return ;
}[/code]and useroot.exe root [] .L myexlib.cpp+ root [] .L importlib.cpp+ root [] importlib();

Cheers,
Philippe.

This is what I actually do.
The architecture of all my “importlib-like” programs looks like this:

[code]#if !defined(CINT) || defined(MAKECINT)
#include “myextlib.cpp”
#endif

void importlib ( … )
{
#if defined(CINT)
gROOT->Reset() ;
#endif
gROOT->ProcessLine(".L myextlib.cpp+") ;

//…
return ;
}[/code]The thing is that myextlib.cpp file contains hundreds of “hello-like” functions (> 10 kLOC) and I’m fed up with compiling it each time I create an importlib-like file in a new directory (it takes ages!).
I would really prefer loading the dll directly. It’s possible with CINT. It should be with ACLiC.
Please…

Cheers,
Z

Hi,

1: never, EVER, call gROOT_>Reset() in a function!
2: CINT knows “hello” because of the dictionary. C++ needs a definition of it.

If you want to compile the file that accesses hello you need a declaration. You need a header file which contains the declarations of functions in your library. There is nothing ROOT specific about that: that’s the way one uses code from libraries (and the reason for Linux package managers to install the headers with the libraries when the xyz-dev[el] packages is installed).

Cheers, Axel.

gROOT->ProcessLine(".L myextlib.cpp+") ; [quote]I’m fed up with compiling it each time I create an importlib-like file in a new directory (it takes ages!).
I would really prefer loading the dll directly[/quote]The .L myextlib.cpp+ will do exactly what you said, it will compile it exactly once … I am confused about the problem (unless the problem is simply that your export lib source code is wrong and is missing the prototypes (aka header file) describing the thinks that you want to import …

Philippe.

[quote]1: never, EVER, call gROOT_>Reset() in a function![/quote]Even if I wrap it in order to clean everything in interpreted mode? #if defined(__CINT__) gROOT->Reset() ; #endif

Yes. It still means that the interpreter must execute:void importlib ( ... ) { gROOT->Reset() ; ....which tells him, please forget everything … including the function you are executing right now.

Philippe.

Thank you both (Actually I thought named scripts and un-named scripts behave the same :blush:).

For my compilation issue, you were both right: headers really helps :wink:
(I got confused by my first C tests).

So below’s how to proceed in:
[ul][li]C[/]
[
]C++[/]
[
]ROOT with ACLiC[/*][/ul]

1. In C

Files (.c files, header useless)

[code]### myextlib.c ###
#include <stdio.h>
int hello()
{
printf (“Hello World!\n”);
return (0) ;
}

importlib.c

int main()
{
hello() ;
return (0) ;
}[/code]
Compilation/Execution (gcc)

gcc -c myextlib.c -o myextlib.o && gcc -shared myextlib.o -o myextlib.dll gcc -c importlib.c -o importlib.o && gcc -L./ -lmyextlib importlib.o -o importlib.exe ./importlib.exe

2. In C++

Files (.cpp and .hpp files, header compulsory)

[code]### myextlib.hpp ###
#include <stdio.h>
int hello() ;

myextlib.cpp ### // header included

#include "myextlib.hpp"
int hello()
{
printf (“Hello World!\n”);
return (0) ;
}

importlib.cpp ### // header included

#include "myextlib.hpp"
int main()
{
hello() ;
return (0) ;
}[/code]
Compilation/Execution (g++)

g++ -c myextlib.cpp -o myextlib.o && g++ -shared myextlib.o -o myextlib.dll g++ -c importlib.cpp -o importlib.o && g++ -L./ -lmyextlib importlib.o -o importlib.exe ./importlib.exe

3. In ROOT with ACLiC

Files (.cpp and .hpp files, header compulsory)

[code]### myextlib.hpp ### // same as standard C++
#include <stdio.h>
int hello() ;

myextlib.cpp ### // same as standard C++

#include "myextlib.hpp"
int hello()
{
printf (“Hello World!\n”);
return (0) ;
}

importlib.cpp ### // the function cannot be called main

#include "myextlib.hpp"
int importlib_root()
{
hello() ;
return (0) ;
}[/code]
Compilation/Execution (within ROOT)

[root_01]> .L myextlib.cpp+ /// creates the file myextlib_cpp.dll [root_02]> gSystem->Load("myextlib_cpp.dll") [root_03]> .L importlib_root.cpp+ [root_04]> importlib_root()NB:[ul]
[*]Once the library myextlib_cpp.dll is created you can link it anywhere along with myextlib.hpp
"ln -s $MYLIBDIR/myextlib_cpp.dll ; ln -s $MYLIBDIR/myextlib.hpp"
OR just “ln -s $MYLIBDIR/myextlib.hpp” if you add myextlib_cpp.dll to LD_LIBRARY_PATH.
You will then just need to type commands root_02, root_03 and root_04. [/li]
[li]To avoid loading the library each time you open Root, add it to your rootlogon.C file (that you can also link in the current directory).
You will then just need to type commands root_03 and root_04 (or just “.x importlib_root.cpp+”).[/li]
[li]Of course, no probs in interpreted mode, root_03 and root_04 can be replaced by
".x importlib_root.cpp"[/li]
[li]All the above libraries can be skimmed: strip myextlib[_cpp].dll[/li][/ul]

Voilà,
Feel free to correct me if I’m wrong or if it sounds awkward.
Cheers,
Z

[quote]Files (.c files, header useless)[/quote]Even in C they are not useless … it just so happen that C upon not seeing a prototype for your function will assume that it takes no argument and return an int … For example see what the C compiler says about:[code]int g() {
return f();
}

float f(int x) {
return x;
}

int main() {
return g();
}[/code]

Cheers,
Philippe.

I have a related problem. I am new to ROOT, and I am trying to import a library of .C code to allow me to do file I/O of our binary data files.

For nonROOT applications, the library is compiled from about 10 source files with GNU make.

What I am looking for is a reasonable best choice howto to try to get it into a form that my ROOT CINT applications can import.

(if you are interested the source is available here: musr.ca/mud/ )

Thanks for any advice

Andrew

Hi Andrew,

As you probably already found out, the best solution is to write a LinkDef file, use rootcint to generate a dictionary source file and combine it with your source into a shared library.

Cheers,
Philippe.