Run external function from root macro

Hi,

The following struggle (I am using root 6.04.14):
I have directories along with my macro in my folder:
[ul]
./src
./effic
./rootmacro.c
[/ul]
I am trying to access the function effic2 that is defined in effic/effic2.hpp and implemented in src/effic2.cpp. My root macro looks very naive:

#include "TFile.h" #include "effic/effic2.hpp" void rootmacro(){ ... effic2(...); ... }
effic/effic2.hpp looks like

#ifndef EFFIC_INC
#define EFFIC_INC
extern "C"
{
  void effic2(int k, int N, double conflevel,
        double& mode, double& low, double& high);
}
#endif  //EFFIC_INC

and src/effic2.cpp looks like

#include "effic/effic2.hpp"
...
extern "C"
void effic2(int k, int N, double conflevel,
      double& mode, double& low, double& high) {...}

When I try to run the macro with

I receive the error message

What can I do to access the effic2 function from my macro?

Hi,

you need to make the implementation known to the interpreter and not just the definition.
There are two ways at least to achieve this:

  1. Include not only the header file but also the .cpp file
  2. Compile the project in the effic directory, obtain a shared library, load the headers and the library in ROOT, namely:
#include "effic/effic2.hpp"
gSystem->Load("effic/lib/libeffic.so");//I invent the name
  1. is to be considered some sort of kludge while 2. is a more scalable solution.

Cheers,
D

I tried the first solution because it seemed to be faster, unfortunately I get the error

IncrementalExecutor::executeFunction: symbol '_Z19normalized_beta_incddd' unresolved while linking [cling interface function]! You are probably missing the definition of normalized_beta_inc(double, double, double) Maybe you need to load the corresponding shared library? IncrementalExecutor::executeFunction: symbol '_Z5brentdddPFddEdPd' unresolved while linking [cling interface function]! You are probably missing the definition of brent(double, double, double, double (*)(double), double, double*) Maybe you need to load the corresponding shared library? IncrementalExecutor::executeFunction: symbol 'gsl_set_error_handler' unresolved while linking [cling interface function]! IncrementalExecutor::executeFunction: symbol 'gsl_set_error_handler_off' unresolved while linking [cling interface function]!

Regarding the second solution: I have the directories effic and src. How do I make a shared library out of them?

Hi,

this error is due probably to the fact that other headers are pulled in by this latter file. The cause is exactly the same as before.
To compile a library, you use a compiler, such as gcc and clang. To obtain a shared library you can do:

g++ -o libMylib.so -fPIC -shared mysource1.cc mysource2.cc ... mysourceN.cc -I path/to/inc1/ -I path/to/inc2/ ... -I path/to/incN/ `root-config --cflags --libs`

Danilo

Thanks a lot for your help. I still have issues. My shred library is using the GNU Scientific Library, which I have under
[ul]./gsl[/ul]
I tried to compile with

Then I used

#include "effic/effic2.hpp" ... R__LOAD_LIBRARY(effic/lib/libEffic.so);
instead of gSystem->Load, and when I run my macro it says

However, gsl_set_error_handler_off is function provided by gsl. The include in src/effic2.cpp is

And this file is in
[ul]./gsl/gsl/gsl_errno.h[/ul]
But it doesn’t find it… Do you know what might be wrong?

Hi,

the gsl library is not properly linked to your library. Can you try

g++ -o libEffic.so -fPIC -shared src/effic2.cpp src/solvers.cpp src/specfunc.cpp -I ./ -I ./gsl/ `root-config --cflags --libs` -l gsl -L  path/to/your/libgsl/

and then, for the runtime, you’ll have to put the “path/to/your/libgsl/” in the LD_LIBRARY_PATH.

perhaps it’s useful for you: you can always build root with the builtin gsl, without relying on the system one with the cmake option

-Dbuiltin_gsl=ON

see root.cern.ch/building-root .

Cheers,
Danilo

[quote=“dpiparo”]the gsl library is not properly linked to your library. Can you try

g++ -o libEffic.so -fPIC -shared src/effic2.cpp src/solvers.cpp src/specfunc.cpp -I ./ -I ./gsl/ `root-config --cflags --libs` -l gsl -L  path/to/your/libgsl/

[/quote]
This worked! Thanks a ton!

Hi there. Are there extra precautions we need to take when compiling said macro? I’m getting undefined reference to a function I defined and loaded this way.

Hi,

we are reviving a 3y old thread here :slight_smile: Could it be possible to have a reproducer with the error message you see in a separate, new post?

Thanks a lot!

Cheers,
Danilo

Hello,

I send you a test macro of what I’m trying to do, plus the src and header for my external “lib”. The output I’m getting is the following:

Processing testCompileWextLib.cc+(“using/zedjet_pythia_10000000_200_g1_p0_z2_d1_jp0_clean.root.root”, “using/dijets_pythia_5000000_200_g1_p0_z2_d3_jp0_clean.root.root”, 50, “Mult”)…
Info in TUnixSystem::ACLiC: creating shared library /home/macros/./testCompileWextLib_cc.so
cling::DynamicLibraryManager::loadLibrary(): /home/macros/testCompileWextLib_cc.so: undefined symbol: _ZN5boost6system16generic_categoryEv
/usr/lib/…/lib64/crt1.o: In function _start': (.text+0x20): undefined reference tomain’
/home/macros/testCompileWextLib_cc_ACLiC_dict.o: In function analiticTopics(std::string, std::string, int, std::string)': testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x24c): undefined reference togetHist(TFile*, std::string, bool)’
testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x28d): undefined reference to getHist(TFile*, std::string, bool)' testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x2cb): undefined reference togetHist(TFile*, std::string, bool)’
testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x309): undefined reference to getHist(TFile*, std::string, bool)' /home/macros/testCompileWextLib_cc_ACLiC_dict.o: In function__static_initialization_and_destruction_0(int, int)’:
testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x578): undefined reference to boost::system::generic_category()' testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x584): undefined reference toboost::system::generic_category()’
testCompileWextLib_cc_ACLiC_dict.cxx:(.text+0x590): undefined reference to `boost::system::system_category()’
collect2: error: ld returned 1 exit status

I see part of the problem comes from the boost lib directly, but the function GetHist is mine and I don’t seem to be able to reach it either.

What should I do?

testCompileWextLib.cc (666 Bytes)
myutility.cc (6.5 KB)
myutility.h (827 Bytes)

Sorry, I must be an idiot. Can you elaborate?

In short, “R__LOAD_LIBRARY” does nothing in an ACLiC (pre)compiled macro.