C到D:结构作为类型并初始化?

C到D:结构作为类型并初始化?,d,ctod,D,Ctod,我有这些C宏,希望将它们转换为纯D(与原始C文件的接口相同) 这是我当前的实现: 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 __bufsiz

我有这些C宏,希望将它们转换为纯D(与原始C文件的接口相同)

这是我当前的实现:

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版本运行良好,但是我可以对代码进行任何调整和修剪吗?它看起来仍然很保守。例如,
kh_init
可以是这样的:

static kstream_t *ks_init(type_t f){
    kstream_t* ks;
    ks.f = f;
    return ks;
  }
但是这个版本给出了一个
精液错误


此外,在
ks_init
ks_destroy
中手动处理内存是否有任何好处?

它会出错,因为您没有在堆栈上分配
kstream\u t
,而是分配一个初始化为
null
的指针。 要在堆栈上分配它,您需要执行以下操作:

但是当您尝试访问它的任何字段时,这仍然会在
main()
中出错,因为只要作用域退出,堆栈分配就会被释放,这在本例中是
ks_init()

您应该在gc上分配它:

编辑:对不起,我没有谈到缓冲区的分配,您可以将maclloc的内存分配给GC,以便他可以为您管理它


但是,你似乎有兴趣把代码移植到惯用的D。然后有一些事情要考虑,你已经找出其中的大部分:

  • 使用数组而不是指针
  • 使用new而不是malloc
  • 将穷人的模板(宏)转换为D模板
  • 在结构中移动方法
  • 最好将命名样式更改为 代码可能如下所示:

    EDIT2:如果不想避免GC,可以将缓冲区设置为静态数组:

    Walter Bright有一个很棒的主题演讲,名为-,他建议避免GC分配,并展示了一些技巧,我推荐。
    然而,我们不能总是避免GC/堆分配,如果数组很大,我们必须使用新的。

    当前在D中实现垃圾收集器的速度很慢(我们正在摆脱它,很快就不再使用GC),虽然它不会那么慢,但大多数时候你并不需要额外的速度,所以你不需要体验使用
    new

    这是一个更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);
    
    
    }
    

    这个问题应该迁移到ks_init(),因为您需要分配稍后在
    ks.f=f行。您需要调用malloc()、calloc()或(D方式)您应该能够简单地做到这一点:
    kstream\u t*ks=new kstream\u t@RobertH:复活节让我离开了一段时间。我的回答是:我现在的“工作”D版本还没有经过测试。我还没有到优化步骤。我有兴趣有一个工作和真正的D版本。此外,有人告诉我,SO的D程序员比SO的其他兄弟姐妹都多。所以我想在这里发帖。@DejanLekic应用了你的建议,但还是得到了seg。错误。如果你得到了分段错误,那一定是我们在这里看不到的一些代码,因为上面的代码在我的工作站上不会产生分段错误……这是@DejanLekic发布的相同想法的一个更完美的答案。但是,我尝试了,但仍然出现了分段错误。我怀疑我必须用显式构造函数编写
    \ukstream\ut
    结构。但我仍然不知道如何去做,事实上,你们正朝着正确的方向前进。我在上面编辑了我的答案。希望能有帮助。是的,我想要一个惯用的D代码,如果它不会显著影响性能的话。目前,性能还不是首要任务。所以都是白痴。哦,错过了“ma”。只是好奇,我们能否避免在构造函数中使用
    新的ubyte[bs]
    ,从而使它与
    @nogc
    兼容。仅供参考,我不太了解“@nogc”,也不知道为什么避免GC实际上更好。但这似乎与性能有关。和以前一样。。。如果您同意由D的GC分配的结构,则可以避免malloc()。
    kstream_t ks;  // still bad
    
    auto ks = new kstream_t;
    
    ks.buf = cast(ubyte*)malloc(__bufsize);
    import core.memory : GC;
    GC.addRange(ks.buf, __bufsize);
    
    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]);
    }
    
    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]);
    }
    
    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);
    
    
    }