To provide a means for ACE-based application developers to avoid
symbol conflicts when multiple versions of ACE are linked to an
application ACE supports versioned namespaces. When
enabled (disabled by default), ACE's versioned namespace support
causes all ACE symbols (classes, free functions, etc) to be
placed within a C++ namespace of the form "namespace
ACE_5_5_1
". For example, the ACE_Reactor
would end up being placed in the versioned namespace like so:
namespace ACE_5_5_1
{
class ACE_Reactor
{
...
};
}
using namespace ACE_5_5_1;
Notice that a using
clause exposes the ACE types
embedded in the versioned namespace back to the global
namespace. This maximizes source code compatibility. ACE
itself does this through the use of two macros:
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
namespace ACE_VERSIONED_NAMESPACE NAME
{
", where
ACE_VERSIONED_NAMESPACE_NAME
by defaults to
namespace name of the form
ACE_major_minor_beta
.
Users may override the default by defining the
ACE_VERSIONED_NAMESPACE_NAME
preprocessor
symbol in their ace/config.h
header file.
ACE_END_VERSIONED_NAMESPACE_DECL
} using namespace
ACE_VERSIONED_NAMESPACE_NAME;
", where
ACE_VERSIONED_NAMESPACE_NAME
is described
above.
Every effort has been made to make the versioned namespace
support in ACE as transparent as possible, including transparent
versioned symbol support in the ACE_Service_Configurator when
the ACE_Service_Configurator macros, such as e.g.,
ACE_FACTORY_DECLARE
, are used appropriately. No
changes to service configurator directives are necessary. For
example, the ACE_Service_Configurator
will
transparently mangle the factory function name in a service
configurator directive on-the-fly, meaning it will only load a
"versioned" factory function name. This allows multiple service
object factory functions, for example, to coexist in the same
process space.
There is, however, at least one caveat with respect to source
code compatibility: any forward declarations of ACE symbols must
also be placed within the versioned namespace. For example, if
you have a forward declaration for ACE_Reactor
in
your application code, you will need to place it within the
configured ACE versioned namespace as follows:
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
class ACE_Reactor;
ACE_END_VERSIONED_NAMESPACE_DECL
This must only be done once, as these macros hide the versioned namespace name details from the application. Alternatively, you could place the forward declaration in a namespace that is an alias of the ACE versioned namespace, e.g.:
namespace Foo = ACE_VERSIONED_NAMESPACE_NAME;
namespace Foo {
class ACE_Reactor;
}
using namespace Foo;
Versioned namespace support in ACE may be enabled by adding
versioned_namespace=1
to your MPC
default.features
file.
ACE developers should place all ACE symbols that are potentially
exposed to the user, including forward declarations in a
versioned namespace using the
ACE_BEGIN_VERSIONED_NAMESSPACE_DECL
and
ACE_END_VERSIONED_NAMESPACE_DECL
macros. Free
functions that are declared to have a C calling convention
(i.e., extern "C"
) should have their names
mangled using the ACE_PREPROC_CONCATENATE
preprocessor. For example:
void ACE_func (void) { ... }
...
ACE_func(); // Call ACE_func()
becomes:
#if (defined (ACE_HAS_VERSIONED_NAMESPACE) \
&& ACE_HAS_VERSIONED_NAMESPACE == 1) \
&& !(defined (_MSC_VER) && _MSC_VER <= 1200)
// MSVC++ 6's preprocessor can't handle macro expansions
// required by the versioned namespace support. *sigh*
# define ACE_FOO_FUNC_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_foo_func)
#else
# define ACE_FOO_FUNC_NAME ACE_foo_func
#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
...
void ACE_FOO_FUNC_NAME (void) { ... }
ACE_FOO_FUNC_NAME(); // Call mangled ACE_foo_func().
The ACE_PREPROC_CONCATENATE
is used rather than a
straight ##
preprocessor concatenation since in the
latter case preprocessor symbols like
ACE_VERSIONED_NAMESPACE_NAME
will not be expanded
if they are concatenated. ACE_PREPROCE_CONCATENATE
forces the preprocessor to expand them during the argument
prescan by calling a macro that itself calls another that
performs the actual concatenation.
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
and
ACE_END_VERSIONED_NAMESPACE_DECL
macros. Doing
so will cause nested namespace to be created, which is not
the desired affect.
$ACE_ROOT/bin/fuzz.pl
script has a sanity
checking test for versioned namespaces that may be of use when
debugging nested namespace issues, and for detecting
BEGIN
/END
mismatches.
Versioned namespace support in ACE may be enabled by adding
versioned_namespace=1
to your MPC
default.features
file. Additional
information about versioned namespaces is available from the Riverace
website.