d:更好C中用d类
原文
如何在D中带betterC使用带有C++链接的类.
在D中,可在-betterC条件下用类.是的,可以!
D中-betterC不能用类的问题是:依赖运行时勾挂和来自D运行时库的类型信息.
而betterC禁止使用运行时类型信息,所以betterC不能用依赖它的设施.但由于不依赖任何运行时库,betterC不限制C和C++的链接.
难点在哪?
实例化extern(C++)类时,有难点,当前最新版编译器,在无以下两点时难取得类的初始内存块.
1:依赖TypeInfo,用typeid(ClassFoo).initializer.
2,创建挂名类的挂名域实例,并复制内存到新分配的缓冲区.
两个选项都有缺点,1在betterC时,只有手动创建和删除一些符号时才行.2也有限制,因为用户不能用普通类析构器.如果不用特殊析构器,可如下轻松取类初化器.
static auto initializer()
{
alias T = typeof(this);
void[__traits(classInstanceSize, T)] t = void;
scope T s = new T;
t[] = (cast(void*)s)[0 .. t.length];
return t;
}
也可自定义析构器来绕过它.但这样就不能raii了.
合理方法
LDC有个取类类型的初化器的__traits(initSymbol)特征,将在规范中描述,且dmd也已实现,只需要创建自定义分配和消灭函数模板.
T alloc(T, Args...)(auto ref Args args)
{
enum tsize = __traits(classInstanceSize, T);
T t = () @trusted {
import core.memory : pureMalloc;
auto _t = cast(T)pureMalloc(tsize);
if (!_t) return null;
import core.stdc.string : memcpy;
memcpy(cast(void*)_t, __traits(initSymbol, T).ptr, tsize);
return _t;
} ();
if(!t) return null;t.__ctor(args);
return t;
}
void destroy(T)(ref T t)
{
static if (__traits(hasMember, T, "__dtor"))
t.__dtor();
() @trusted {
import core.memory : pureFree;
pureFree(cast(void*)t);
}();
t = null;
}
用此两个函数,可如下在betterC中分配新类实例:
extern(C++) class Foo
{
this(int a, float b)
{
this.a = a * 2;
this.b = b;
}
int a;
float b;
bool c = true;
}
extern(C) int main()
{
Foo foo = alloc!Foo(2, 2.0f);
scope(exit) destroy(foo);
int a = foo.a; // 4
float b = foo.b; // 2.0
bool c = foo.c; // true
return 0;
}
浙公网安备 33010602011771号