[QtRoot] Link problem of a class derived from TQtWidget

Hi, I am having a trouble porting my application to Windows.
It includes a class that inherits TQtWidget. The class contains Q_OBJECT macro to gain signal/slot functionality.
The application is built and works fine on Linux, but cannot compile on Windows7 + Visual Studio 2010. Below are the error messages.

[quote] link /LIBPATH:“c:\Qt\4.8.0\lib” /NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMEN
TAL:NO /MANIFEST /MANIFESTFILE:“release\test.intermediate.manifest” /SUBSYSTEM:W
INDOWS “/MANIFESTDEPENDENCY:type=‘win32’ name=‘Microsoft.Windows.Common-Controls
’ version=‘6.0.0.0’ publicKeyToken=‘6595b64144ccf1df’ language=’’ processorArch
itecture=’
’” /OUT:release\test.exe @C:\Users\kameoka\AppData\Local\Temp\nm975E.
tmp
moc_canvaswidget.obj : error LNK2001: unresolved external symbol “public: static struct QMetaObject
const TQtWidget::staticMetaObject” (?staticMetaObject@TQtWidget@@2UQMetaObject@
@B)"
release\test.exe : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: ‘“c:\Program Files (x86)\Microsoft Visual Studio 10.0
\VC\BIN\link.EXE”’ : return code '0x460’
Stop.
NMAKE : fatal error U1077: ‘“c:\Program Files (x86)\Microsoft Visual Studio 10.0
\VC\BIN\nmake.exe”’ : return code '0x2’
Stop.[/quote]
It seems that Visual Studio somehow failed to link a moc-processed object file of the custom class.
There is no problem linking a class with signal/slots derived from a native Qt class.
I attached a minimum program files that reproduces the error.
Have anyone experienced the same problem?

Sorry, I forgot to attach the files.
test.zip (1.58 KB)

Hello , Thank you for your report.

Frankly, I did no try QtRoot with Visual Studo 10 yet.
I used
Qt libraries 4.8.1 for Windows (VS 2008, 234 MB)
from qt.nokia.com/downloads/
I found they have added VS10 too.
Qt libraries 4.8.1 for Windows (VS 2010, 235 MB)
I still need to install these (VS10 + Qt 4.8.1 with VS10) to reproduce your issue.

What about next week? Can you wait?

Have you by chance tried your example wth VS2008?

Hi, thank you for reply.
So you don’t have problem inheriting TQtWidget at least with VS2008 and Qt4.8.1, right?

I am sorry. I have checked to find your issue has nothing to do with VS2010 and Qt 4.8 combo.
The message:

moc_canvaswidget.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const TQtWidget::staticMetaObject" (?staticMetaObject@TQtWid get@@2UQMetaObject@@B) is present with VS2008 and Qt 4.7.1 too.
The symbol TQtWidget::staticMetaObject is defined by “root/lib/libGQt.lib” import library.
You can check this with the command:

dumpbin /EXPORTS lib\libGQt.lib >libGQT.exp.log The rootcint.pri is to make sure this library is present for the M$ LINK stages.
You may want to add the

message ($$LIBS) into your test.pro to check this fact yourself.

In the other words, I did reproduce your issue. However, I had not time (due holidays )to find the reason #-o yet.

Google says, this is because one mixes the debug and optimized version of the (Qt and/or Root) lib/dll.
I need to re-install QtRoot onto my laptop to get the clear answer to confirm / deny that theory yet. (I did screw it)

The symbol in question, namely, static struct QMetaObject const TQtWidget::staticMetaObject" (?staticMetaObject@TQtWidget
is the internal symbol of the libGQt.dll. It is not needed outside of that DLL if everything is configured properly. It should be neither exported nor imported.

Another unrelated issue with your code. Please, consider to move the implementation of the virtual methods from the header canvaswidget.hh to canvaswidget.cxx file.

Thank you for reply.

[quote]Google says, this is because one mixes the debug and optimized version of the (Qt and/or Root) lib/dll.
I need to re-install QtRoot onto my laptop to get the clear answer to confirm / deny that theory yet. (I did screw it)[/quote]
I built both Qt and ROOT by “release” configuration.

The issue is VC+±related. It is not Qt/ROOT related.
May I suggest you some workaround :unamused: to try?
Can you include your class into QtRoot “libGQT.dll”, i.e. add it to the root/graf2d/qt/inc and root/graf2d/qt/src and adjust root/graf2d/qt/Module.mk makefile like this

[code]Index: root/graf2d/qt/Module.mk

— root/graf2d/qt/Module.mk (revision 3511)
+++ root/graf2d/qt/Module.mk (working copy)
@@ -34,7 +34,7 @@
GQTMOCH := (MODDIRI)/TQtWidget.h (MODDIRI)/TQtEmitter.h
(MODDIRI)/TQtClientFilter.h (MODDIRI)/TQtClientGuard.h
(MODDIRI)/TQtClientWidget.h (MODDIRI)/TQtTimer.h \

  •             $(MODDIRI)/TQtRootSlot.h
    
  •             $(MODDIRI)/TQtRootSlot.h    $(MODDIRI)/canvaswidget.h
    

GQTMOC := (subst (MODDIRI)/,(MODDIRS)/moc_,(patsubst %.h,%.cxx,(GQTMOCH))) GQTMOCO := (GQTMOC:.cxx=.o)
[/code]
and rebuild ‘root’ ?

CustomCanvas.tar.gz (2.83 KB)

$ tar -tzvf CustomCanvas.tar.gz -rwxr-xr-x fine/None 164 2012-04-10 13:06 expert/RootForum/14461/main.cc -rwxr-xr-x fine/None 341 2012-04-10 13:02 expert/RootForum/14461/test.pro -rw-r--r-- fine/None 4700 2012-04-10 13:11 root/graf2d/qt/Module.mk -rwxr-xr-x fine/None 474 2012-04-10 12:42 root/graf2d/qt/inc/canvaswidget.h -rwxr-xr-x fine/None 1372 2012-04-10 12:41 root/graf2d/qt/src/canvaswidget.cxx Let me know the outcome.

Hi, sorry for late reply. I’ve been out on a conference.

I think your idea will work, but it is unpractical to embed my class in the QtRoot DLL every time.
They describe here http://qt-project.org/faq/answer/when_creating_a_library_with_qt_windows_and_using_it_in_an_application_then how to export and import symbols in DLL.
I tried to add __declspec macro to the class definition of TQtWidget as below and compile the QtRoot libraries, but VC just issues “syntax error”.

Well
Just a short response.

  1. What you tried can not work
  2. The issue is not trivial and well-known ( see ifh.de/CHEP97/main_pap.htm ).

What that 15 years old talk was about. The code from one shared lib (DLL) can not directly access the global variable defined by another shared lib (DLL). One needs to define the special function to “export” that global variable value. In Unix realm such function is created on fly by linker. In MS world this issue should be solved from within the code itself.

15 years ago we introduced a special utility (see root.cern.ch/viewvc/trunk/build/ … iew=markup ) to avoid the pollution of the C++ code with the “strange” CPP macros. This gave us a reasonable compromise. The utility eliminated the need to use the CPP macros ( this is what that Qt link is about) to export the ROOT functions and methods correctlty. However, it did not solve the “export of the global variable” issue. The later is what you had faced.

I think the simplest solution is to create your own QWidget (or QFrame) with TQtWigdet inside.
In fact, this is what Qt “designer” will do for you automatically. There are the other solutions too . However, such solution will make your code Win32 specific. This is what we tried to avoid from very begginning.

Let me know whether I need elaborate further.

Hi, thank you very much for the detailed answer.

[quote]I think the simplest solution is to create your own QWidget (or QFrame) with TQtWigdet inside.
In fact, this is what Qt “designer” will do for you automatically. [/quote]
Do you mean that I should use TQtWidget as a delegate rather than inherit it?
In that case is it possible to change the behaviours of the virtual functions without inheritance?

[quote=“kame”]…Do you mean that I should use TQtWidget as a delegate rather than inherit it?[/quote] Yes, I do. [quote=“kame”] In that case is it possible to change the behaviours of the virtual functions without inheritance??[/quote] I am wondering if your goal is to change the widget behavior rather the C++ class property. The former is possible via delegation. The parent widget can change the way your application processes the GUI events. See for example root.cern.ch/root/html532/TQtWid … :SetRootID The SetRootID was designed to redirect the TQtWidget mouse event handling to the parent widget.

Please, take in account that your trouble doesn’t come from the TQtWidget inheritance per se. You can subclass TQtWidget. The “only” problem the subclass can not be in possession of its own signal and slots ](*,) .