Writing Ttree with custom class from standalone CMake project

Hello,

I would like to do something similar to the tree2a.C example (root/tree2a.C at master · root-project/root · GitHub) but in a standalone application instead of a ROOT macro.

I have written a very simple CMake project to do this (based on the example macro) but I run into compilation issues, which I don’t know how to solve.

Here is my main.cpp file:

#include <TFile.h>
#include <TObject.h>
#include <TTree.h>

class Event : public TObject {
public:
    Int_t fNumber;

    Event() {
        fNumber = 0;
    }

    ClassDef(Event, 1)
};

int main() {
    TFile f("tree.root", "recreate");
    TTree t("t", "An example TTree");

    auto *event = new Event();

    t.Branch("event", &event);

    for (Int_t i = 0; i < 100; i++) {
        event->fNumber = i;
        t.Fill();
    }

    t.Write();

    return 0;
}

And my CMakeLists.txt file:

cmake_minimum_required(VERSION 3.16)
project(root_tree_example)

set(CMAKE_CXX_STANDARD 11)

# Find ROOT
find_package(ROOT CONFIG REQUIRED)

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} PUBLIC ${ROOT_LIBRARIES})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${ROOT_INCLUDE_DIRS})

I get the following compilation error:

====================[ Build | root_tree_example | Debug ]=======================
/usr/bin/cmake --build /mnt/c/WSL-Ubuntu-20.04/github/root-tree-example/cmake-build-debug --target root_tree_example -- -j 6
Scanning dependencies of target root_tree_example
[ 50%] Building CXX object CMakeFiles/root_tree_example.dir/main.cpp.o
[100%] Linking CXX executable root_tree_example
/usr/bin/ld: CMakeFiles/root_tree_example.dir/main.cpp.o: in function `Event::Event()':
/mnt/c/WSL-Ubuntu-20.04/github/root-tree-example/main.cpp:9: undefined reference to `vtable for Event'
/usr/bin/ld: CMakeFiles/root_tree_example.dir/main.cpp.o: in function `TClass* ROOT::Internal::GetClassHelper<Event>(bool, bool, std::integral_constant<bool, true>)':
/home/lobis/apps/root/install/include/TClass.h:568: undefined reference to `Event::Class()'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/root_tree_example.dir/build.make:102: root_tree_example] Error 1
make[2]: *** [CMakeFiles/Makefile2:76: CMakeFiles/root_tree_example.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/root_tree_example.dir/rule] Error 2
make: *** [Makefile:118: root_tree_example] Error 2

If I remove the line ClassDef(Event, 1), the program compiles and runs successfully but the tree only has some “default” (TObject?) members, not the ones I declared:

image

I can also run this main.cpp as a ROOT macro (root main.cpp) and it will successfully create the tree as I want:

image

How can I achieve the same result but from compiled code? Thanks.

Hi,
if you “just” want to read/write a custom C++ type with ROOT you don’t need to inherit from TObject or use ClassDef, but you need to generate dictionaries and link them to your program.

We should soon have better docs about this topic (as soon as I get to it), but for now this might be useful: GitHub - eguiraud/root_dictionaries_tutorial: A tutorial on creating ROOT dictionaries to perform I/O of custom C++ classes .

Cheers,
Enrico

P.S.
@pcanal feel free to correct me/elaborate

1 Like

Thanks, the examples in your repository are really helpful :slight_smile:

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