Qt-interest Archive, March 2002
building Qt 3.x with Visual C++ .Net
Message 1 in thread
Hi,
there has been some discussion lately on how to build Qt 3.x with Microsoft's latest C++ compiler.
As Tom pointed out, the problem is that the Qt header files use Q_EXPORT on template classes, which is something that must not be
done. An old Microsoft Technical Article from 1996 named "DLLs for Beginners" explicitly mentioned this. Should that article be
easier to find? Should the compiler issue warnings, if not errors? I fully concur ;-)
FWIW: after fixing Qt's headers, there was no problem to compile, link and run Qt 3.0.2 with Visual C++ .Net beta 2 (it will be
several more weeks until the official version is released in Germany...).
Volker mentioned that this introduces other problems, but for the life of me, I don't see them (yet?). Everything just appears to
work. Hm, what am I doing "wrong" here?
To reproduce: the changed header files (hope I did not miss any) are under:
http://soeren.fietzke.bei.t-online.de/qt3vc7/qt3vc7.zip
Extract into the standard Qt include directory and rebuild Qt *from scratch*. I have used 'configure' without any arguments, so it
created the standard shared release version makefiles:
cd %QTDIR%
nmake clean
configure
nmake
BTW: dllexport itself does not have any impact on new/delete code. If one appears to have problems with these functions, it is most
likely a CRT conflict, solvable by compiling app and dlls with the same CRT flags.
Cheers,
Soeren (who hopes he did not miss something obvious... :)
Message 2 in thread
In order to do this safely, three things have to happen:
(1) You are correct: The import/export define in templates should be
removed. Qt has not applied these consistently, so I suspect some are just
legacy code.
(2) Although VS will issue a "non-standard extention" warrning,
instantations in the library need to be marked "extern". This prevents the
importer from constructing its own instantation.
(3) To be sure that the "extern" in the .h file is actually compiled, the
dll needs to either use it, or the library will require an empty .cpp file
that simply #includes the header to force compilation.
Just achieving compilation is not enough: we have conducted extensive tests
in both VS6 and VS7 to determine this. If all three things are not done, the
dll either will not compile, or the importer will construct its own version
of the instantation.
Regards,
Mark
----- Original Message -----
From: "Soeren Fietzke" <Soeren.Fietzke@t-online.de>
To: "Qt Interest List" <qt-interest@trolltech.com>
Sent: Monday, March 11, 2002 7:26 AM
Subject: building Qt 3.x with Visual C++ .Net
> Hi,
>
> there has been some discussion lately on how to build Qt 3.x with
Microsoft's latest C++ compiler.
> As Tom pointed out, the problem is that the Qt header files use Q_EXPORT
on template classes, which is something that must not be
> done. An old Microsoft Technical Article from 1996 named "DLLs for
Beginners" explicitly mentioned this. Should that article be
> easier to find? Should the compiler issue warnings, if not errors? I fully
concur ;-)
>
> FWIW: after fixing Qt's headers, there was no problem to compile, link and
run Qt 3.0.2 with Visual C++ .Net beta 2 (it will be
> several more weeks until the official version is released in Germany...).
>
> Volker mentioned that this introduces other problems, but for the life of
me, I don't see them (yet?). Everything just appears to
> work. Hm, what am I doing "wrong" here?
>
> To reproduce: the changed header files (hope I did not miss any) are
under:
> http://soeren.fietzke.bei.t-online.de/qt3vc7/qt3vc7.zip
>
> Extract into the standard Qt include directory and rebuild Qt *from
scratch*. I have used 'configure' without any arguments, so it
> created the standard shared release version makefiles:
> cd %QTDIR%
> nmake clean
> configure
> nmake
>
>
> BTW: dllexport itself does not have any impact on new/delete code. If one
appears to have problems with these functions, it is most
> likely a CRT conflict, solvable by compiling app and dlls with the same
CRT flags.
>
> Cheers,
> Soeren (who hopes he did not miss something obvious... :)
>
> --
> List archive and information: http://qt-interest.trolltech.com
Message 3 in thread
Hi Mark,
> In order to do this safely, three things have to happen:
> (1) You are correct: The import/export define in templates should be
> removed. Qt has not applied these consistently, so I suspect some are just
> legacy code.
yep, to me that looks like to root of the troubles.
> (2) Although VS will issue a "non-standard extention" warrning,
> instantations in the library need to be marked "extern". This prevents the
> importer from constructing its own instantation.
Note that I left the Q_EXPORT on template instantiations in the header files.
Why would it be bad if the importer creates their own specializations? They
are supposed to be weak symbols, so that the linker in the end will pick
one of them and discard the others. Because it can't discard the one in the
DLL, it should pick that one (in theory, haven't tested that). In any case, the
worst that can happen is code bloat, not malfunction. Compiler option /Gy
may help to reduce code bloat...
> (3) To be sure that the "extern" in the .h file is actually compiled, the
> dll needs to either use it, or the library will require an empty .cpp file
> that simply #includes the header to force compilation.
Er, that defeats the purpose of using templates a bit?!? The instantiations would
then be dependent on some library.
I would also not be surprised about "duplicate symbol" errors in such a scenario.
>
> Just achieving compilation is not enough:
True. But I achieved compilation (without warnings), linking (without warnings
other than "blalib not used to import any symbol") and
running examples and Designer (without any runtime problems).
What other problems should I look for?
> we have conducted extensive tests
> in both VS6 and VS7 to determine this. If all three things are not done, the
> dll either will not compile, or the importer will construct its own version
> of the instantation.
Again: the latter is supposed to happen, so I do not see a problem with it -- as
long as the linker leaves at most one specialization per module.
Cheers,
Soeren
Message 4 in thread
Hi Soeren,
Thanks for the comments. I've added a couple of comments to try to make my
original message just a bit clearer.
> > (2) Although VS will issue a "non-standard extention" warrning,
> > instantations in the library need to be marked "extern". This prevents
the
> > importer from constructing its own instantation.
>
>
> Note that I left the Q_EXPORT on template instantiations in the header
files.
The fact that Qt contains instatiations with export/import statements means
they were intended to be exported/imported and used.
> Why would it be bad if the importer creates their own specializations?
They
> are supposed to be weak symbols, so that the linker in the end will pick
> one of them and discard the others. Because it can't discard the one in
the
> DLL, it should pick that one (in theory, haven't tested that).
If the extern keyword is not used, the importer will not use the dll's
version. I can send you code to play with, if you like.
In any case, the
> worst that can happen is code bloat, not malfunction. Compiler option /Gy
> may help to reduce code bloat...
Putting aside Qt, if the instantiation in your code differs from the the one
in a dll (perhaps the dll was recompiled with a different header than the
one you are using) the instatiations may act differently.
>
> > (3) To be sure that the "extern" in the .h file is actually compiled,
the
> > dll needs to either use it, or the library will require an empty .cpp
file
> > that simply #includes the header to force compilation.
>
> Er, that defeats the purpose of using templates a bit?!? The
instantiations would
> then be dependent on some library.
> I would also not be surprised about "duplicate symbol" errors in such a
scenario.
One very good reason to instantiate within a dll is to reduce code bloat. If
you don't export that instantiation, then you need not have an instantiation
at all. And, if the extern keyword is not present, you will not be able to
import it. The instantiations are not dependent on some library, they are in
the dll you propose to use.
If on the other hand, you simply want to use templates and not instantiate
any templates in the dll, the whole conversation is moot.
However, Qt is a dll with instantiations in it. To use them, you need to do
more than you originally suggested. In addition to cleaning up the
import/export statements, you need to actually export any used
instantiations of templates in the dll.
> > If all three things are not done, the
> > dll either will not compile, or the importer will construct its own
version
> > of the instantation.
>
> Again: the latter is supposed to happen, so I do not see a problem with
it -- as
> long as the linker leaves at most one specialization per module.
If your plan is to export instantiations, then clearly this is not supposed
to happen.
Are you confusing raw templates with instantiated templates?
There is nothing wrong with not exporting instantiations -- however, if the
dll contains them, and you intend to use them, you need to make sure they
are imported.
Hope this is a little clearer.
Mark
> Cheers,
> Soeren
>
Message 5 in thread
Hi,
>> (2) Although VS will issue a "non-standard extention" warrning,
>> instantations in the library need to be marked "extern". This prevents the
>> importer from constructing its own instantation.
> Note that I left the Q_EXPORT on template instantiations in the header files.
> Why would it be bad if the importer creates their own specializations? They
> are supposed to be weak symbols, so that the linker in the end will pick
> one of them and discard the others. Because it can't discard the one in the
> DLL, it should pick that one (in theory, haven't tested that). In any case, the
> worst that can happen is code bloat, not malfunction. Compiler option /Gy
> may help to reduce code bloat...
doesn't code like:
------------------------------------------------------
template <class T>
class counter
{
public:
static int cnt_;
counter() { cnt_++; }
~counter() { --cnt_; }
};
template <class T>
int counter<T>::cnt_ = 0;
/* to be used like
* class xyz: public counter<xyz> {};
*/
------------------------------------------------------
produce _two_ counter<T>::cnt_ variables when used both in the (DLLed)
library and in the application?
/eno
Message 6 in thread
Hi Eno,
well, that problem is solvable:
in MSVC 6.0:
it will be necessary to derive a class from the desired specialization and export that one:
class DLLEXPORT counter_int : counter<int>
{
};
Warning C4275 will be emitted, but a very simple example will work as
expected: dll and app share the same variable cnt_.
MSVC .NET (beta 2):
either use the above (does not generate a warning any more, so seems to be safe)
or write this in the header file:
template class DLLEXPORT counter<int>;
I would not say that these are the officially blessed methods, but it works for me.
Let me know if I missed something or if you would like to have a look my test project files.
Regards,
Soeren
>
> doesn't code like:
> ------------------------------------------------------
> template <class T>
> class counter
> {
> public:
> static int cnt_;
> counter() { cnt_++; }
> ~counter() { --cnt_; }
> };
>
> template <class T>
> int counter<T>::cnt_ = 0;
>
> /* to be used like
> * class xyz: public counter<xyz> {};
> */
> ------------------------------------------------------
>
> produce _two_ counter<T>::cnt_ variables when used both in the (DLLed)
> library and in the application?
>
> /eno
>