1

const(和in

考虑有 C 函数:

unsigned int foo(const unsigned int a);

const对生成的代码没有影响,就好像代码通过编译一样,const如果没有,什么都不会破坏const——所以 C 编译器在编译时只使用它作为代码契约说明符。

是否有任何努力在 D 中编写uint foo(in uint a);uint foo(const uint a);调用此函数?这是否可以帮助 D 编译器生成更有效的调用代码foo,或者这将不起作用(至少对于值类型参数)?

refout

有C函数

unsigned int bar(unsigned int *a);

我是否必须uint bar(uint* a);在将其翻译为 D 时使用指针语法,或者我可以写uint bar(ref uint a);(或者uint bar(out uint a);,如果我知道这a仅用于输出,来自文档bar)?ref和下是否还有其他隐藏机制out,或者它们看起来只是简单的指针?out当调用超出 D 范围时,D会生成“胶水代码”以将参数初始化为其默认值吗?

更新 1:我编写了简单的代码来测试如何在参数中处理refs 和outs — 它们实际上至少对于ints 来说似乎是普通指针,但out在传递时不会重置为初始值 — C 端仍然可以读取它的值并修改它,所以它有效地表现得像ref。我不确定,当我以这种方式使用东西时,是否会出现与 GC 相关的问题。

Update2:在函数结果中使用ref而不是指针也可以按预期方式工作。const仍然未经测试,我不知道如何检查它而不需要反汇编我的程序。

4

2 回答 2

1

由于 C 不会破坏参数,因此事物将与任何类型限定符链接。

程序员有责任确保在 extern(C) 函数原型中声明的 D 类型限定符实际上与 C 函数的作用相匹配。

我不会使用 ref 或任何带有 C 代码的 ref,因为 C 中不存在引用,因此它可能不会按照您的预期进行(如果确实如此,它可能随时中断,因为您处于未指定状态世界)。

编辑:关于 const。C 中的 const 和 D 中的 const 不是一回事(它在 D 中是可传递的,而不是在 C 中)。再次由程序员来确定函数的参数是否可以根据 D 语义进行 const 限定。

于 2012-04-06T21:40:51.143 回答
1

in(与 相同const scope)在 C 中不存在,因为在 Cscope中不存在。并且out也不ref存在于 C 中。不要将它们与extern(C)函数一起使用。如果你在函数的参数中使用它们,编译器可能会报错extern(C),但如果没有,我也不会感到惊讶。如果它碰巧奏效了,那你就“幸运”了。它可能随时停止工作。如何ref和如何out实现是编译器的实现细节。通常,您应该只对实际存在于 C 中的函数使用修饰符extern(C)。D 的编译器不会做任何魔术来使 D 的东西在extern(C)函数上工作。extern(C)

我知道的唯一两个例外是pureand nothrow,因为它们根本不影响调用约定,只是 D 是否允许您从某些函数中调用它们。因此,您可以将 C 函数标记为pure和/或nothrow。但是如果你用 标记它(或者你可能会得到讨厌的错误),你最好确保该函数实际上是纯函数pure- 与nothrow. 从技术上讲,@safe、@trusted 和 @system 也可以使用,但 C 函数确实应该保留为默认值 - @system - 因为它们是 C 函数。

不,将参数标记为 C 函数const不太可能帮助任何优化。如果参数是值类型,那么const从调用者的角度来看是没有意义的。无论如何都会复制该参数。它只与引用类型有关。在 的情况下extern(C),这将仅限于带有指针的指针和结构(直接或间接)。那里可能有一些优化,但我不会打赌——尤其是 dmd,它通常不会像 gdc 和 ldc 那样优化代码。充其量,编译器可以做的是确定在该调用之后,传入的变量没有改变,这可能会在调用者中启用其他优化,但它高度依赖于调用者和编译器。

更值得关注的是 C 参数是否真的是const. 一般来说,你很好,但在 C 中,丢弃const和更改变量是合法的,而在 D 中,它不是。这主要可能与immutable数据有关(字符串文字是一个主要示例)。如果有任何东西试图实际改变数据,您将面临段错误或更糟的风险。一般来说,这不应该是标记为的 C 函数参数的问题const(尽管有时可能是这样),但这绝对意味着将参数标记为constC 没有时几乎肯定是一个坏主意。如果你这样做,你需要确保变量的值永远不会被 C 函数实际改变。因为如果你把它标记为const然后 C 函数对其进行变异,您将遇到错误。

所以,总而言之,我想说的是,一般来说,你应该只extern(C)用 C 修饰符标记函数,而不是 D 特定的修饰符,并且你通常不应该将参数标记为const除非它们在 C 中以这种方式标记。如果你知道C函数实际上是什么pure,你可以把它标记为pure。如果你知道它实际上是nothrow,你可以用 标记它nothrow。如果您知道 C 函数从未改变过参数,那么您可以将其标记为const. 但是你应该对此非常保守,否则你在你的代码中造成讨厌的错误。

如果您还没有阅读这些页面,请阅读:

http://dlang.org/interfaceToC.html
http://dlang.org/htomodule.html

于 2012-04-06T22:37:18.067 回答