How to use linkdef.h

Dear experts,
I’m confused about linkdef.h. Seeing https://root.cern/manual/python/#loading-c-libraries-with-dictionaries , it seems that we don’t need to add ROOT.gInterpreter.ProcessLine() in the python file. But it doesn’t work without ROOT.gInterpreter.ProcessLine() , is there something wrong with my usage method?

#ifdef __CINT__
#pragma link C++ class MyClass;
#pragma link C++ function MyFunction;
#pragma link C++ global MyGlobal;
#endif

linkdef.h (127 Bytes)

__
Please read tips for efficient and successful posting and posting code

_ROOT Version:6.24/06
_Compiler:gcc version 8.3.0 (GCC)


Yes, you are on the right track!

You should also add this at the beginning right after #ifdef __CINT__:

// Standard preamble: turn off creation of dictionaries for "everything":
// we then turn it on only for the types we are interested in.
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

You can find some nice examples on how to generate your own dictionaries here:

If you are building your own library, I would recommend using cmake, like in this example.

Only that you are building a library and not an executable. So add_executable(readwrite_twoints readwrite_twoints.cpp twoints.cpp) has to be replaced with add_library(readwrite_twoints SHARED readwrite_twoints.cpp twoints.cpp) (and changing the filenames too obviously).

Feel free to follow up here if you have more questions!

Hi jonas
Thanks for your answer. I download the code in git and follow it’s steps, but I still meet some questions.

cmake_minimum_required(VERSION 3.9)
project (readwrite_twoints CXX)

message(STATUS “Looking for ROOT”)
find_package(ROOT REQUIRED COMPONENTS RIO)
add_library(readwrite_twoints SHARED readwrite_twoints.cpp twoints.cpp )
target_link_libraries(readwrite_twoints ROOT::RIO)
target_include_directories(readwrite_twoints PRIVATE
${CMAKE_CURRENT_SOURCE_DIR})
ROOT_GENERATE_DICTIONARY(twoints_dict twoints.hpp MODULE readwrite_twoints LINKDEF LinkDef.h)

this is my CMakeLists.txt, I only change the add_executable to add_library, and I get a libreadwrite_twoints.so, and I change main function to “f” function in readwrite_twoints.cpp

#include “TFile.h”
#include “twoints.hpp”
#include
int main(){return 0;}
int f() {
{
// write the ti object to an output file
TwoInts ti(1, 2);
TFile out_f(“f.root”, “recreate”);
out_f.WriteObjectAny(&ti, “TwoInts”, “ti”);
std::cout << “Written TwoInts(” << ti.GetA() << ", " << ti.GetB() << “)\n”;
}
TFile in_f(“f.root”);
auto *tiptr = in_f.Get(“ti”);
std::cout << “Read TwoInts(” << tiptr->GetA() << ", " << tiptr->GetB() << “)\n”;

                               return 0;
                               }

and I write a test.py in order to call this “f” function

import ROOT
ROOT.gSystem.Load('./build/libreadwrite_twoints.so')
ROOT.f()

but it doesn’t work

Traceback (most recent call last):
File “/scratchfs/cepc/wangshengyi/test/cmake2/test.py”, line 5, in
ROOT.f()
File “/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.24.06-3455f/x86_64-centos7-gcc8-opt/lib/ROOT/_facade.py”, line 192, in _fallback_getattr
raise AttributeError(“Failed to get attribute {} from ROOT”.format(name))
AttributeError: Failed to get attribute f from ROOT

but it work when I add this line in my python file

ROOT.gInterpreter.ProcessLine('#include "./readwrite_twoints.cpp"')

I think using linkdef can omit this line, or Is my usage wrong?

Hi, you are still missing a function declaration in the header, otherwise it doesn’t get picked up by the dictionary generation. If you add a line with int f(); to twoints.hpp it should work!

1 Like

Hi jonas
Thanks to your advice, the question is solved! I add

int f();

in .hpp and add

#pragma link C++ function f;

in LinkDef.h, and now I can call the function “f” in python without ROOT.gInterpreter.ProcessLine().

By the way, is every c++ function and class needed to be added in LinkDef.h before we call it in the python file?

Cheers,
ShengYi

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