Это для MSVC.
Само пространство имен не искажается, но имя пространства имен включается в имя функции (или объекта), когда происходит искажение имени. Этот процесс не задокументирован, но описан здесь.
Отвечая на ваши конкретные вопросы, прыгая вокруг:
1) Стандартное поведение в отношении изменения имени отсутствует. Что на самом деле говорит Стандарт, так это то, что реализации обеспечивают C-совместимую компоновку для конструкций extern "C"
:
7.5.3 [Спецификации связи]
Каждая реализация должна обеспечивать связь с функциями, написанными на языке программирования C, "C", и связь с функциями C++, "C++". [Пример:
complex sqrt(complex); // C + + linkage by default
extern "C" { double sqrt(double); // C linkage }
— конец примера]
В конечном счете, это означает, что, поскольку C не имеет понятия namespace
s, если extern "C"
функции или объекты в пространствах имен, ваши экспортированные имена потеряют квалификацию пространства имен. Это ведет к...
3) Да, у вас могут быть проблемы со связью. Попробуй это:
main.h
#ifndef MAIN_API
# define MAIN_API __declspec(dllexport)
#endif
namespace x
{
extern "C" MAIN_API void foo();
};
namespace y
{
extern "C" MAIN_API void foo();
};
main.cpp
#include <cstdlib>
#include <iostream>
using namespace std;
#define MAIN_API __declspec(dllexport)
#include "main.h"
void x::foo()
{
cout << "x::foo()\n";
}
void y::foo()
{
cout << "y::foo()\n";
}
int main()
{
}
Это вызовет ошибку компоновщика, потому что версии x::foo()
и y::foo()
с extern "C"
потеряли свою идентификацию пространства имен, поэтому они имеют точно такое же имя: foo()
2) Лучшие практики в этом отношении. Если вы должны экспортировать C-ABI для функций в пространствах имен, вы должны быть осторожны, чтобы имена, которые вы в конечном итоге экспортируете, не совпадали. В какой-то степени это противоречит цели использования namespace
в первую очередь. Но вы можете сделать что-то вроде этого:
#ifndef MAIN_API
# define MAIN_API __declspec(dllexport)
#endif
namespace x
{
extern "C" MAIN_API void x_foo();
};
namespace y
{
extern "C" MAIN_API void y_foo();
};
person
John Dibling
schedule
15.11.2010