d:更好C中用d类

原文
如何在D中带betterC使用带有C++链接.
D中,可在-betterC条件下用类.是的,可以!
D-betterC不能用的问题是:依赖运行时勾挂和来自D运行时库类型信息.
betterC禁止使用运行时类型信息,所以betterC不能用依赖它的设施.但由于不依赖任何运行时库,betterC不限制C和C++的链接.

难点在哪?

实例化extern(C++)类时,有难点,当前最新版编译器,在无以下两点时难取得初始内存块.
1:依赖TypeInfo,用typeid(ClassFoo).initializer.
2,创建挂名类的挂名域实例,并复制内存到新分配的缓冲区.
两个选项都有缺点,1betterC时,只有手动创建和删除一些符号时才行.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;
}
posted @   zjh6  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示