これはMSVC用です。
名前空間自体は名前マングルされませんが、名前のマングルが発生すると、名前空間の名前が関数 (またはオブジェクト) の名前に組み込まれます。このプロセスは文書化されていませんが、ここで説明されています。
飛び回って特定の質問に答える:
1) 名前マングリングに関して、標準で定義された動作はありません。標準が実際に述べていることは、実装がextern "C"
構造体に 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()
{
}
extern "C"
-ed バージョンのx::foo()
とy::foo()
は名前空間 ID を失っている ため、これによりリンカー エラーが発生します。そのため、最終的にはまったく同じ名前になります。foo()
2) これに関するベスト プラクティス。名前空間内の関数の C-ABI をエクスポートする必要がある場合は、エクスポートする名前が同じにならないように注意する必要があります。namespace
これは、そもそもa を使用する目的にある程度反します。しかし、次のようなことができます:
#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();
};