Home | News | Documentation | Download

Shared library stopped working when external functions were added

Dear experts,

I am having trouble creating a shared library that I want to use in Python, and this problem appears when I call functions in other .cxx file that don’t belong to a class.
Since I don’t have permission to share all the code, I’ll just schematize which is the problem.

I have the following package structure:

PackageName
  |
  - lib/
  - obj/
  - utils
  |     |
  |     - MyMasterFile.py
  | 
  - Root
  |     |
  |     - ClassA.cxx
  |     - ClassB.cxx
  |     - UtilsFunctions.cxx
  |     - LinkDef.h
  | 
  - Package
  |     |
  |     - ClassA.h
  |     - ClassB.h
  |     - UtilsFunctions.h
  |     - ProgressBar.h
  | 
  - Makefile

The source file UtilsFunctions contains functions that will be called from ClassB and maybe from other python files (if that’s possible). In addition to that, ClassB will always be called from ClassA. So here’s the calling structure:

//============================================================
// In Root/ClassA.cxx
#include "ClassA.h"
void ClassA::doSomething()
{
    ClassB foo();
    foo.doSomethingInB();
}
//============================================================
// In Package/ClassA.h
#ifndef CLASSA_H
#define CLASSA_H
#include "Package/ClassB.h"
class ClassA {
public:
   void doSomething();
}
#endif



//============================================================
// In Root/ClassB.cxx
#include "ClassB.h"
void ClassB::doSomethingInB()
{
    float val = Function1();
}
//============================================================
// In Package/ClassB.h

#ifndef CLASSB_H
#define CLASSB_H
#include "Package/UtilsFunctions.h"
class ClassB {
public:
   void doSomethingInB();
}
#endif



//============================================================
// In Root/UtilsFunctions.cxx
void Function1()
{
    # calculate something here
}
//============================================================
// In Package/UtilsFunctions.h
#ifndef UTILSFUNCTIONS_H
#define UTILSFUNCTIONS_H
void Function1()
#endif
# In utils/MyMasterFile.py

import ROOT
ROOT.gSystem.Load("libPackageName.so")

tool = ROOT.ClassA()
tool.doSomething()

The LinkDef.h file contains the following:

#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclass;

#pragma link C++ class ClassA+;
// #pragma link C++ class ClassB+;
// #pragma link C++ defined_in "UtilsFunctions.h"; (this I don't know if I need to comment or not)

#endif

And finally, in my Makefile I compile all .cxx files to object files, then the dictionary is created and it’s all linked. All compilation goes well, but when I run the python file I get a message (pointing to ClassA in the .py file) saying that ClassA is not defined:

cling::DynamicLibraryManager::loadLibrary(): /path/to/tool/PackageName/lib/libPackageName.so: undefined symbol: _ZTIN4ROOT8Internal20TTreeReaderValueBaseE
Traceback (most recent call last):
  File "utils/MyMasterFile.py", line 64, in <module>
    main()
  File "utils/MyMasterFile.py", line 52, in main
    tool = ClassA()
NameError: global name 'ClassA' is not defined

I tried before adding UtilsFunctions and everything run fine, so this problem appears when I add these functions. I believe it’s something related with how I generated the dictionary, or compilation, but I can’t decipher it. Also I leave my Makefile attached (I added the .txt extension so I can upload it )Makefile.txt (1.8 KB).

So to conclude, the question is: what can I do to get this thing working using UtilsFunctions?, because I know it works when I don’t add those

Thank you very much in advance!
Cheers!
Francisco


ROOT Version: 6.20/06
Platform: lxplus


Hi @fsili,

IMHO, the problem is due to a symbol that cannot be resolved, as seen in this line:

cling::DynamicLibraryManager::loadLibrary(): /path/to/tool/PackageName/lib/libPackageName.so: undefined symbol: _ZTIN4ROOT8Internal20TTreeReaderValueBaseE

The previous symbol sems to be exported by libTreePlayer.so. Can you please add -lTreePlayer in your Makefile and see if it solves the problem?, i.e.

LINKLIBSIN = -L$(shell root-config --libdir) -lCore -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lGui -lRooStats -lRooFit -lHistFactory -lXMLParser -pthread -lRooFitCore -lTreePlayer -lm -ldl -lFoam -lMinuit -Llib

Cheers,
J.

Hi @jalopezg ,
Thank you very much for your reply! Indeed that solved that problem, but another one similar appeared. This time it reads:

python: symbol lookup error: /path/to/tool/PackageName/lib/libPackageName.so: undefined symbol: _ZN12NtupleLooper7m_utilsEv

where NtupleLooper is my ClassB.

Thank you very much,
Cheers,
Francisco

Are you linking the corresponding object generated for ClassB? Maybe you left that commented in the LinkDef.h file?

Yes. I tried both with that line commented and not commented :confused:
However, I think that this is strange because the python file never calls ClassB. This class is only called from within ClassA.

The relevant parts of the Makefile also look good to me.

Can you copy here the declaration of NtupleLooper::m_utils? Maybe is it a non-instance, i.e. static, member that was declared but not defined?
-just making a guess, but it is hard without the sources-

I’ve just corrected that issue. The problem was that I changed the code after posting it here. I put the functions inside UtilsFunctions into a class. Now that I changed it back to plain functions it’s working smoothly.

However, when changing everything back to functions, I’m not able to call them (functions from UtilsFunctions) from the master python script. For example, if I define a function function1 inside UtilsFunctions.h and its source code is in UtilsFunctions.cxx, if I try to call it from MyMasterFile.py like

import ROOT
ROOT.gSystem.Load("libPackageName.so")
ROOT.function1()

it complains with an attribute error AttributeError: function1. This problems doesn’t appear when I call ClassA as

tool = ClassA()
tool.MethodFoo()

I also checked that I have this line not commented

#pragma link C++ defined_in "UtilsFunctions.h";

inside LinkDef.h

Do I need to add something when calling the function?

Thank you very much for your help! And sorry for these lots of questions

Cheers,
Francisco

Hi @fsili,

Indeed, it seems that the functions declared in UtilsFunctions.h are not in the generated dictionary. Could you please confirm that these functions are not in a namespace or so? In any case, could you try the following to check if that workarounds the problem?

#pragma link C++ all function

I will invite @pcanal to this thread as he might know what the issue might be. @pcanal, you can skip the whole thread and only read the latest @fsili post.

Cheers,
Javier.

If I remember correctly, you need to give the full path name here.

However this should not make a difference for a function.

What command line did you use to generate the dictionary?

Hi!

I changed it and gave the full path and now it works!

This solution by @jalopezg also worked!

Thank you both very very much for your help! :smiley:

Cheers,
Francisco

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.