2017-04-11 14 views
2

我有这些C宏,并希望将它们转换为纯D(因为与原始C文件接口)。C到D:struct为type并初始化?

#define __KS_TYPE(type_t) \ 
    typedef struct __kstream_t { \ 
     unsigned char *buf; \ 
     int begin, end, is_eof; \ 
     type_t f; \ 
    } kstream_t; 


#define __KS_BASIC(type_t, __bufsize) \ 
    static inline kstream_t *ks_init(type_t f) \ 
    { \ 
     kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \ 
     ks->f = f; \ 
     ks->buf = (unsigned char*)malloc(__bufsize); \ 
     return ks; \ 
    } \ 
    static inline void ks_destroy(kstream_t *ks) \ 
    { \ 
     if (ks) { \ 
      free(ks->buf); \ 
      free(ks); \ 
     } \ 
    } 

这是我目前实施:

import std.stdio; 
import core.stdc.config; 
import core.stdc.stdlib; 

struct __kstream_t(type_t) { 
    ubyte *buf; 
    int begin, end, is_eof; 
    type_t f; 
    } 

mixin template __KS_BASIC(type_t, ubyte __bufsize){ 
    // mixin(__KS_TYPE!type_t); 
    alias kstream_t = __kstream_t!type_t; 
    static kstream_t *ks_init(type_t f) 
    { 
    kstream_t *ks = cast(kstream_t*)calloc(1, kstream_t.sizeof); 
    ks.f = f; 
    ks.buf = cast(ubyte*)malloc(__bufsize); 
    return ks; 
    } 
    static void ks_destroy(kstream_t *ks) 
    { 
    if (ks) { 
     free(ks.buf); 
     free(ks); 
     writeln("Destroyed struct."); 
    } 
    } 

} 

void main(){ 
    mixin __KS_BASIC!(int, 12); 

    auto ks = ks_init(14); 
    ks.buf[0] = 125; 
    writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]); 
    ks_destroy(ks); 


} 

的d版本目前运行良好,但我可以做任何调整和代码的微调?它仍然看起来非常C-ISM。例如,kh_init可以仅仅是这样的:

static kstream_t *ks_init(type_t f){ 
    kstream_t* ks; 
    ks.f = f; 
    return ks; 
    } 

不过这个版本给一个sementation fault

此外,在D版本中,手动处理内存ks_initks_destroy是否有任何好处?

+3

这个问题应该被迁移到http://codereview.stackexchange.com –

+1

ks_init()不能像你说的,因为你需要分配你以后在'ks.f = F使用kstream_t对象; '线。你需要调用malloc(),calloc()或OR(D方法),你应该可以简单地做到这一点:'kstream_t * ks = new kstream_t;' – DejanLekic

+0

@RobertH:复活节假期让我暂时离开了。所以这里是我的回应:我现在所使用的'工作'D版本未经测试。我还没有进入优化步骤。我有兴趣有一个工作和真正的D版本。此外,我被告知,SO比其他兄弟姐妹拥有更多的D程序员。所以我想在这里发帖。 – biocyberman

回答

0

由于您没有在堆栈上分配kstream_t,而是分配了一个初始化为null的指针,所以存在段错误。 分配它在栈上,你会怎么做:

kstream_t ks; // still bad 

但是这仍然会在main()段错误,当您尝试访问任何字段,因为堆栈分配是尽快释放的范围退出其在此案例ks_init()

则应该将它分配在GC:

auto ks = new kstream_t; 

编辑:对不起,我没谈分配的缓冲区,你可以给maclloc'd存储到GC这样他就可以管理它为你

ks.buf = cast(ubyte*)malloc(__bufsize); 
import core.memory : GC; 
GC.addRange(ks.buf, __bufsize); 

但是似乎你有兴趣移植塔t code to idiomatic D.然后有几件事要考虑,你已经想出了其中的大部分:

  1. 使用数组而不是指针。
  2. 使用new而不是malloc。
  3. 将穷人的模板(宏)转换为D模板。
  4. 在struct中移动方法。
  5. 最好更改命名风格D Style

的代码可能看起来像:

import std.stdio; 

struct Kstream(T) { 
    ubyte[] buf; 
    int begin, end, is_eof; 
    T f; 

    this(T f, ubyte bs) 
    { 
     this.f = f; 
     this.buf = new ubyte[bs]; 
    } 

    ~this() 
    { 
     writeln("Destroyed struct."); 
    } 
} 

void main(){ 

    auto ks = Kstream!int(14, 12); 
    ks.buf[0] = 125; 
    writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]); 
} 

EDIT2:如果你wan't避免GC,你可以让缓冲区的静态数组:

import std.stdio; 

struct Kstream(T, size_t N) { 
    ubyte[N] buf; 
    int begin, end, is_eof; 
    T f; 

    this(T f) 
    { 
     this.f = f; 
    } 

    ~this() 
    { 
     // we cannot call writeln in @nogc code 
     //writeln("Destroyed struct."); 
    } 
} 

@nogc 
void main(){ 
    auto ks = Kstream!(int, 12)(14); 
    ks.buf[0] = 125; 

    // we cannot call writeln in @nogc code 
    //writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]); 
} 

Walter Bright有一个伟大的基调称为Memory DisAllocation - slides,他建议避免GC分配和sho我使用一些技术来做到这一点,我推荐它。
但是,我们不能总是避免GC /堆分配,如果数组很大,我们必须使用新的。
D中垃圾收集器的当前实现是缓慢的(我们正在摆脱它,很快就没有GC了),尽管当时它的速度并不慢,大部分时间你并不需要那额外的速度,所以你不用费力使用new

+0

这是对@ DejanLekic。但是,我尝试过,仍然出现分段错误。 – biocyberman

+0

我怀疑我必须用显式构造函数编写'__kstream_t'结构。但我仍然不知道如何去做。 – biocyberman

+1

事实上,你正朝着正确的方向前进。我在上面编辑了我的答案。希望能帮助到你。 –

0

这是一个更D的版本,从@ DejanLekic的评论和@Sahmi回答中得到了一些启发。我发布了一个答案,因为我不想更改原始问题。

import std.stdio; 
import core.stdc.config; 
import core.stdc.stdlib; 

struct __kstream_t(type_t) { 
    ubyte *buf; 
    int begin, end, is_eof; 
    type_t f; 

    this(type_t f, ubyte bs){ 
    this.f = f; 
    this.buf = cast(ubyte*)malloc(bs);//Can this be avoided or more D? 
    } 

    } 

mixin template __KS_BASIC(type_t, ubyte __bufsize){ 
    alias kstream_t = __kstream_t!type_t; 
    static kstream_t* ks_init(type_t f){ 
    auto ks = new kstream_t(f, __bufsize); 
    return ks; 
    } 

    static void ks_destroy(kstream_t *ks) 
    { 
    if (ks) { 
     destroy(ks); 
     writeln("Destroyed struct."); 
    } 
    } 

} 


void main(){ 

    mixin __KS_BASIC!(int, 12); 

    auto ks = ks_init(14); 
    ks.buf[0] = 125; 
    writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]); 
    ks_destroy(ks); 


} 
+0

和以前一样......如果你确定了由D的GC分配的结构,你可以避免malloc()。 – DejanLekic