【发布时间】:2012-04-10 04:44:18
【问题描述】:
C++ 严重依赖 C 风格来导出和导入函数(如果有的话,不是类/接口),因此失去了面向对象的风格,这在许多方面使导出的接口变得晦涩难懂。
可以使用 D 编程语言以面向对象的方式导出接口吗?我可以用 D 接口包装 C++(纯)类吗?有哪些可能的考虑因素?这种方法可行吗?
【问题讨论】:
C++ 严重依赖 C 风格来导出和导入函数(如果有的话,不是类/接口),因此失去了面向对象的风格,这在许多方面使导出的接口变得晦涩难懂。
可以使用 D 编程语言以面向对象的方式导出接口吗?我可以用 D 接口包装 C++(纯)类吗?有哪些可能的考虑因素?这种方法可行吗?
【问题讨论】:
您可以找到 D 的 C++ 互操作性频谱概览here。
通过 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
}
接口I 上的D 的extern(C++) 会导致接口布局复制带有伴随C++ 编译器中的虚函数的单继承C++ 类的布局。
函数声明 createC 上的相同属性导致函数复制伴随 C++ 编译器中等效函数的修改和调用约定。
配套编译器对:DMD/DMC++、GDC/g++、LDC/Clang。通过坚持使用虚函数和 C ABI 进行直接函数调用,通常可以与非伴随编译器进行互操作。
请注意,createC 函数在 C++ 中返回 I*,而在 D 中仅返回 I。这是因为 D 接口和类是隐式引用类型。
在更典型的实际使用中,createC 函数更可能是 extern(C) 而不是 extern(C++)(然后是 C++ 端的 extern "C"),以实现编译器之间的更大互操作性,或更直接 -使用 DLL 时的前向运行时链接。
extern(C++) 目前有一些限制;目前无法告诉 D extern(C++) 声明在哪个命名空间中,将 D 限制为只能链接到全局命名空间中的 C++ 符号。
【讨论】: