我正在努力对 Nim 背后的政策下定决心expression has no address
。特别是,我有一个 C 函数,它接受一些数据缓冲区的指针(+ 长度等)。我知道这个函数不会修改数据。简化:
type
Buffer = object
data: seq[float]
proc wrapperForCCall(buf: Buffer) =
# accessing either buf.addr nor buf.data.addr produces
# Error: expression has no address
# workaround:
var tmp = buf.data # costly copy
callToC(tmp.len, tmp.addr) # now it works
一方面这是有道理的,因为参数的行为似乎与let
绑定完全一样,它也“没有地址”。另一方面,我对手册中的这句话感到困惑:
var 参数对于有效的参数传递从来不是必需的。
据我所知,避免复制数据的唯一方法是:
- 将参数传递为
buf: var Buffer
- 传递引用,即使用
ref object
.
在这两种情况下,这表明我的函数修改了数据。此外,它在调用者站点上引入了可变性(即用户不能再对他们的缓冲区使用 let 绑定)。对我来说关键问题是:既然“我知道”callToC
是只读的,我可以说服 Nim 在没有副本的情况下允许这两个不变性吗?我看到这很危险,因为我必须确定调用是不可变的。因此,这将需要某种“不安全地址”机制,允许强制指向不可变数据的指针?
还有我对参数地址的最后一个谜团:我试图通过将类型更改为Buffer {.bycopy.} = object
. 在这种情况下,副本已经在调用时发生,我希望现在可以访问该地址。为什么在这种情况下也拒绝访问?