[Qt-interest] Q_OBJECT in DLL - Release build warnings

Oliver.Knoll at comit.ch Oliver.Knoll at comit.ch
Mon Feb 8 11:55:30 CET 2010


Catalin Roman wrote on Monday, February 08, 2010 10:50 AM:

> This is my first post, so please let me know gently if this is the
> wrong place to seek answers

Hi there and welcome :)

>  to my following problem. 
> I'm building a DLL using Qt 4.6 and Qt Creator 1.3.0. The main class
> of the DLL has the Q_OBJECT macro declared in the .h file because I'm
> using signals/slots. When I build in Release mode, 

So I read it implicitly that it works in debug mode, right?

> I get 4 warnings
> concerning staticMetaObject, metaObject(), qt_metacast() and
> qt_metacall() saying "redeclared without dllimport attribute after
> being referenced with dll linkage/previous dllimport ignored".

These "redeclared without dllimport" warnings are typical for wrong "DLL export/import" declarations, typically due to a missing or wrong DEFINE in the project settings.

So without knowing the exact problem in your case I am giving you a rather generic answer how it /should/ work:

First, for each DLL project, I define a header such as (for library Foo):

// FooDLL.h
#ifndef __FOO_DLL_H_
#define __FOO_DLL_H_

#include <QtGlobal>

#ifdef FOO_EXPORT
# define FOO_API Q_DECL_EXPORT
#else
# define FOO_API Q_DECL_IMPORT
#endif

#endif // __FOO_DLL_H_

Note the usage of the Qt Q_DECL_EXPORT / Q_DECL_IMPORT macros: they expand to the __declspec(dllimport/export) thing on Windows (using the Visual Studio compiler) and to "nothing" everywhere else (IIRC). So they come quite handy here.


Next, let's assume we want to export the *whole* following class from our Foo library:

#include <QtCore/QObject>
#include "FooDLL.h"
...

class FOO_API Foo : public QObject {
  Q_OBJECT
public:
  Foo();
  virtual ~Foo();

  void doFoo();
  void doBar();
  ...
signals:
  void signalFoo();
  ...
private:
  void doSomething();
};


Now the crucial thing here is off course that you DEFINE FOO_EXPORT within your "Foo" project, but that you DON'T DEFINE it for every other project (that is using the Foo library). This way the FOO_API will become the proper Q_DECL_EXPORT (when building the library) or Q_DECL_IMPORT respective (when "importing" / using the library from any other project).

Typically this is done in your Foo.pro like:

DEFINE += FOO_EXPORT

(or in Visual Studio, right-click on your project -> Properties -> C/C++ -> Preprocessor and define it there for BOTH DEBUG and RELEASE configurations!)

If however - my preferred way - you only want to export /certain/ methods, this should (and does, in my case) also work:

class Foo : public QObject {
  Q_OBJECT
public:
  FOO_API Foo();
  FOO_API virtual ~Foo();

  FOO_API void doFoo();
  void doBar();
  ...
signals:
  void signalFoo();
  ...
};


That is, only the (public) methods Foo(), ~Foo() and doFoo() are exported and hence can be called from another library/*.exe. In the above example doBar() however can *not* be called. Well, technically your code would compile if you would call doBar() from any other place than the Foo library, but you would get a linker error! This gives you an additional "package visibility" level :) And since you are only exporting the really needed methods this also results in a *slightly* smaller DLL ;)


To answer your concrete question again, I assume that you either

- Did not properly export your class or
- You forgot to DEFINE the corresponding "EXPORT" value in your release configuration


Cheers, Oliver
-- 
Oliver Knoll
Dipl. Informatik-Ing. ETH
COMIT AG - ++41 79 520 95 22



More information about the Qt-interest-old mailing list