D の C++ 相互運用性スペクトルの概要については、こちらを参照してください。
オブジェクト指向スタイルの相互運用性は、D のinterface
構造によって提供されます。
C++ 側
#include<iostream>
class I // Our interface-by-convention
{
public:
virtual void foo() = 0;
void bar() // OK, non-virtual members do not affect binary compatibility
{
/* ... */
}
};
class C : public I
{
private:
int a;
public:
C(int a) : a(a) {}
void foo()
{
std::cout << a << std::endl;
}
};
// This function will be used from the D side
I* createC(int a)
{
return new C(a);
}
D側
extern(C++) interface I
{
void foo();
final void bar() // OK, non-virtual members do not affect binary compatibility
{
/+ ... +/
}
}
// Link `createC` from the C++ side
extern(C++) I createC(int a);
void main()
{
I i = createC(2);
i.foo(); // Write '2' to stdout
}
extern(C++)
インターフェイスの DI
により、インターフェイス レイアウトは、コンパニオン C++ コンパイラの仮想関数を使用して、単一継承の C++ クラスのレイアウトを複製します。
関数宣言の同じ属性createC
により、関数は、対応する C++ コンパイラの同等の関数のマングリングおよび呼び出し規則を複製します。
コンパニオン コンパイラ ペア: DMD/DMC++、GDC/g++、LDC/Clang。仮想関数と直接関数呼び出し用の C ABI に固執することで、非コンパニオン コンパイラと相互運用できることがよくあります。
この関数はC++ と D だけでcreateC
返されることに注意してください。これは、D のインターフェイスとクラスが暗黙的に参照型であるためです。I*
I
より典型的な実世界での使用では、コンパイラ間の相互運用性を高めるため、または DLL を使用する場合のより単純なランタイム リンクのために、createC
関数は(そしてC++ 側で) よりextern(C)
も可能性が高くなります。extern(C++)
extern "C"
extern(C++)
現在、いくつかの制限があります。現在、extern(C++)
宣言がどの名前空間にあるかを D に伝えることはできず、D はグローバル名前空間の C++ シンボルにのみリンクできるように制限されています。