【问题标题】:How should I handle C-strings in D?我应该如何处理 D 中的 C 字符串?
【发布时间】:2009-08-21 20:31:44
【问题描述】:

我正在将 C 库的头文件转换为 D 模块,并且想知道如何处理 C 字符串。

使用 DMD 1,这可行:

void f(char* s);  // Definition for C library's function.

但使用 DMD 2(我个人使用,但我希望模块同时适用于两者)字符串是 const,因此要使用模块来获得相同的代码来工作需要

void f(const(char)* s);  // Definition for C library's function.

我该怎么办?只需使用char* 并使“客户端”代码以某种方式使字符串可变?还是根据编译代码的编译器版本修改类型?如果是前者,使它们可变的最佳方法是什么?我认为 .dup 会做到这一点,但编译器没有它。如果是后者,我将如何去做?我试过这个:

version (D_Version2) {
    alias const(char)* charptr;
} else {
    alias char* charptr;
}

void f(charptr s);

但是,遗憾的是,DMD 2 版本不是 DMD 1 的有效代码,并且版本块中的所有代码都必须是编译代码的编译器的有效代码,即使该代码不会包含在生成的可执行文件中。所以目前代码在两者中都可以编译,但你必须先修改别名,正如你可以想象的那样,这并不理想。

【问题讨论】:

    标签: string d


    【解决方案1】:

    您可以使用mixin 构造来使用并非在所有版本中都有效的特定于语言版本的代码。示例:

    static if(version_major<2)
    {
        alias char* charptr;
    }
    else
    {
        mixin("alias const(char)* charptr;");
    }
    

    关于您的实际问题,我建议您在将 C 库与 C++ 连接时执行相同的操作 - 为 D2 定义一个类型为 const(char)*,为 D1 定义一个 char*,但仅在适当时使用它(例如,如果函数需要一个char* 作为要写入的缓冲区,将const(char)* 命名为像“charptr”这样的通用名称可能是不合适的。 LPCSTR 可以工作 ;)

    我不明白“使它们可变的最佳方法是什么”这个问题。

    【讨论】:

    • 你好。我应该付钱给你:]。混合技巧不起作用; Error: identifier 'charptr' is not defined。这就说得通了;我认为实际上没有任何函数使用缓冲区,但我会记住这一点。回复LPCSTR:我认为我的unix 敏感性会因此而被冒犯。 cstring?
    • 代码 sn-p 对我有用。你有import std.compiler(声明version_major的模块)吗?
    • 我现在做到了;同样的结果。 v2.0.31
    • 实际上,它甚至不适用于 DMD 1。如果我使用 version(D_Version2) { mixin() } else { alias } DMD 1 有效,但 DMD 2 得到相同的结果。
    • 没关系,我是个白痴(导入模块高于定义:o)。
    【解决方案2】:

    不要为此使用 mixins,它是不适合这项工作的工具。您真正需要的是“版本”语句,您可以在此处的条件编译页面中阅读它:http://www.digitalmars.com/d/2.0/version.html

    它不会编译/查看不同版本的代码。这允许为不同的 D 版本或不同的操作系统构建不同的代码。

    Mixins 可能有效,但它是一个笨重的工具,没有突出显示的代码(在引号内)并且过于复杂。版本语句非常适合这个问题。

    【讨论】:

    • “它不会编译/查看不同版本的代码。”绝对不正确。 version 语句是一个 AST 节点,因此在考虑删除它之前先对其进行解析。语言的更改使有效 D2 的代码无法解析为 D1,并且您不能将无法解析的代码放入 version 语句中。您认为 version 语句的行为类似于 C 预处理器(无效的定义块甚至没有 lexed),而 version 语句并非如此。
    • 嗯,你似乎是对的。我使用以下代码对其进行了测试,该代码在删除 cmets 时没有出现错误: //version (ABCDE) //{ int a = [5, 4]; //} 看起来它应该是正确的。这很奇怪,因为可能总是有代码只能为特定版本编译。但是,使用 mixins 仍然是错误的工具,因为我们没有更好的工具:O,我认为 D 是完美的...:P
    • 你上面的代码解析就好了:它是一个类型、一个标识符和一个数组字面量初始化器。这被解析成一个 AST 节点就好了。直到编译器运行语义传递并看到类型不匹配它才会出错。 |我觉得 version 语句应该在编译过程的早期被认为是实际有用的。
    猜你喜欢
    • 2012-07-01
    • 1970-01-01
    • 2021-07-11
    • 2021-09-13
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多