Missing slot member function fixed by adding user define constructor

ROOT Version: 6.32.00
Platform: Ubuntu 22.04
Compiler: gcc 11.40
Cmake: 3.22.1

I am writing a standalone GUI program and I want to handle the termination for cleaning up. So I follow the tutorial and send TRootCavnas::CloseWindow() signal to TerminationHandler::Terminate(). I compiled successfully but failed to clean up after I pressed the ‘X’ button on top right corner of window. And the error information is below

IncrementalExecutor::executeFunction: symbol '_ZN18TerminationHandler9TerminateEv' unresolved while linking symbol '__cf_5'!
You are probably missing the definition of TerminationHandler::Terminate()
Maybe you need to load the corresponding shared library?
Error in <TClingCallFunc::make_wrapper>: Failed to compile
  ==== SOURCE BEGIN ====
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"
__attribute__((used)) __attribute__((annotate("__cling__ptrcheck(off)")))
extern "C" void __cf_5(void* obj, int nargs, void** args, void* ret)
{
   ((TerminationHandler*)obj)->Terminate();
   return;
}
#pragma clang diagnostic pop
  ==== SOURCE END ====
Error in <TClingCallFunc::Exec(address, interpVal)>: Called with no wrapper, not implemented!

But I “fixed” it through adding an empty constructor to class TerminationHandler. I have no idea why it can run now. I use Ubuntu22.04, ROOT 6.32.00, gcc 11.40, cmake 3.22.1. I made a small demo to reproduce this problem. I have commented the empty constructor in termination-handler.h(.cpp) to make it broken. Again, the program exits gracefully with empty constructor, but break when without it.

Another method to solve this is to put the definition of member function into the header file with declaration. In my case, just put everything in termination-handler.cpp into termination-handler.h.

And I test this on another machine, CentOs 7, ROOT 6.28.04, gcc 9.3.0, cmake 3.26.4. Nothing went wrong and the program exits normally with or without the empty constructor. But I can’t test with other enviroment now.

By the way, are there any easier method to handle the CloseWindow? My current method needs a slot for ROOT signal. So I have to write an RQ_OBJECT class and tell compiler (or interpreter?) with LinkDef.h file. I think it’s a little complex.

CMakeLists.txt (1.6 KB)
LinkDef.h (310 Bytes)
main.cpp (696 Bytes)
termination-handler.cpp (231 Bytes)
termination-handler.h (246 Bytes)

Hi,

I am sorry to read you experience this issue. Let me add @bellenot in the loop.

Cheers,
D

You’re right, the constructor is needed. Is that a big issue for you? If it is, then maybe @pcanal knows why it is needed…

It’s not a big problem and it doesn’t break my program after adding the constructor. Actually an empty destructor can also fix it like the constructor. I am curious about why it works now.

Newer linker have the default feature of 'not linking against shared if they are not needed. Without the explicit constructor or destructor for TerminationHandler, there is nothing in the library that the main.cpp` is using directly.

To change the behavior you need to use -Wl,--no-as-needed