Qt-In-Namespace

From Qt Wiki
Revision as of 09:01, 25 February 2015 by Maintenance script (talk | contribs)
Jump to navigation Jump to search


Qt in Namespace

The Qt-in-Namespace feature serves as a tool to handle certain scenarios involving multiple configurations of Qt more gracefully. E.g. before Qt-in-Namespace a Qt 3 based application in Linux would immediately segfault as soon as it tries to dlopen() a shared object that is linked to Qt 4. With the Qt in namespace feature not only can the crash be prevented, but under certain circumstances this combination might actually "work".

The core of the feature's implementation consists of wrapping "all of Qt code" into a pair of macros

QT_BEGIN_NAMESPACE

and

QT_END_NAMESPACE

. Both macros usually expand to nothing, but they expand to "namespace xxx {" and "}", respectively, when Qt is configured with the option "-qtnamespace xxx"". The macros are defined in

<qglobal.h>

The feature is part of Qt since Qt 4.4. Keeping the feature in a working state is, unfortunately, a bit tedious and influences code that gets integrated into Qt.

To help with this, all contributors to the Qt source code are kindly asked to follow the set of rules given below.

Rules for namespaced code:

This concerns code in

main/src/{corelib,gui,}

and in

main/tools/designer

but not in

main/src/3rdparty

. As a rule of thumb: If it contributes to one of "the Qt" libraries that end up in

lib/*

and if it is "Qt" code, it is "namespaced code".

  1. All occurrences of
    QT_BEGIN_NAMESPACE
    
    and
    QT_END_NAMESPACE
    
    must be balanced with respect to
    #if/#ifdef
    
    etc. preprocessor directives. Most notably this applies to all
    QT_NO_<FEATURE>
    
    branches.
  2. All code that is not a preprocessor directive or a comment must be wrapped in
    QT_BEGIN_NAMESPACE
    
    and
    QT_END_NAMESPACE
    
    . As a rule of thumb this applies do all definitions and declarations concerning types, objects etc with identifiers starting with 'q' or 'Q'.
  3. All
    #include
    
    lines go outside the
    QT_BEGIN_NAMESPACE  QT_END_NAMESPACE
    
    .
  4. Forward declarations of items in non-namespaced code go outside.
  5. As a special exception
    QT_DECLARE_METATYPE
    
    lines go outside.
  6. Q_INIT_RESOURCE
    
    inside. However, the Makefile dependencies are inadequate, so make sure to remove all qrc_.cpp files manually if you have troubles when "namespacing" old code.
  7. If we are in a header file there is usually already a
    QT_{BEGIN,END}''HEADER
    
    pair (or needs to be added) for other reasons. In this case
    QT_BEGIN_NAMESPACE
    
    follows immediately the
    QT_BEGIN_HEADER
    
    line, and
    QT_END_NAMESPACE
    
    precedes the
    QT_END_HEADER
    
    line. To be consistent in style with existing code there should be a single empty line between the
    QT''{BEGIN,END}''HEADER
    
    and
    QT''{BEGIN,END}''NAMESPACE
    
    lines.
  8. Since not all compilers we support adhere to The Standard we cannot use namespaced friend classes within some other class definition without declaring the friend class properly first. As a workaround, declare the friend class first within a
    QT''{BEGIN,END}_HEADER block
    
    .
  9. Since not all compilers we support adhere to The Standard we cannot declare external functions locally within other functions. As a workaround, declare the external function on namespace scope.

h3. Rules for namespace aware code:

This concerns everything in

main/'''

that is not "namespaced code" and any end user code that wishes to use the Qt-in-Namespace feature:

  1. All forward declarations of types, functions and objects that are in "namespaced code" must be namespaced and their use must be "namespace qualified", i.e. written as
 QT_BEGIN_NAMESPACE
 class QCheckBox;
 class QComboBox;
 QT_END_NAMESPACE

This is admittedly ugly but needed. A simple

using namespace QT_NAMESPACE

unfortunately does not help as

 namespace QT_NAMESPACE {  }
 using namespace QT_NAMESPACE;
 class QString;

will declare QString at global namespace which will be distinct from our

QT_NAMESPACE::QString

and cause compiler or linker errors later.

  • A
    QT_BEGIN_NAMESPACE
    
    and
    QT_END_NAMESPACE
    
    wrapper is also needed when extending a namespace that itself lives in namespaced code. This situation typically appears when extending the QtTest namespace in auto tests.

Making code namespace aware can be given a headstart by running

find . -name ''''.cpp' -o -name ''''.h' -exec perl -pie 's:^class Q (.*);:QT_ADD_NAMESPACE_PREFIX($1);: {}

but it looks a bit cleaner if only

QT_BEGIN_NAMESPACE

and

QT_END_NAMESPACE

are used.

Rules for other code:

Everything else including end user code that does not need the feature and end user code that is not even aware of Qt at all does not need to be changed.

Related:

TheDebugger can handle namespaced code as if it were "native" Qt.