我正在努力确定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
。在这种情况下,复制已在呼叫时发生,我希望现在可以访问该地址。为什么在这种情况下也拒绝访问?
您可以buf.data
通过使用shallowCopy来避免深拷贝,例如:
var tmp: seq[float]
shallowCopy tmp, buf.data
的{.byCopy.}
编译指示仅影响调用约定(对象即是否得到在堆叠或通过引用传递。
您不能使用地址的buf
任何部分或地址的任何部分,该地址或地址的任何部分都不能位于ref
或后面,ptr
因为将值作为非var参数传递会保证被调用方不会修改该参数。该shallowCopy
内置的是一个不安全的功能,规避这样的保证(我记得这表明shallowCopy
应该适当地改名unsafeShallowCopy
以反映并有一个新的shallowCopy
,其中第二个参数是一个var
参数也可以)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句