我在Buf
中有一大块内存我要传递给C库,但是库将使用超过单个调用生命周期的内存。
我知道这可能有问题,因为垃圾收集器可以移动内存。
为了传入Str
,Nativecall docs说“如果C函数要求字符串的生命周期超过函数调用,则必须手动编码参数并将其作为CArray [uint8]传递”并且有一个这样做的示例,基本上:
my $array = CArray[uint8].new($string.encode.list);
我的问题是:我必须为Buf
做同样的事吗?万一它被GC移动了?或者GC会将我的Buf
留在原处吗?对于一个短字符串,这不是什么大问题,但对于大型内存缓冲区,这可能是一个昂贵的操作。 (例如,参见Archive::Libarchive,您可以使用tar文件传入Buf
。该代码是否有问题?
multi method open(Buf $data!) {
my $res = archive_read_open_memory $!archive, $data, $data.bytes;
...
有没有(可能有吗?应该有吗?)trait
上的某种Buf
告诉GC不要移动它?我知道如果我向Buf
添加更多数据可能会有麻烦,但我保证不这样做。对于一个不可变的Blob
怎么样?
你可以在MoarVM上使用它,至少在目前,只要你在本机代码需要的时候保持对perl 6中的Blob
或Buf
的引用,并且(在Buf
的情况下)你不要写一个可能导致调整大小的写入。
MoarVM在托儿所内部分配Blob
/ Buf
对象,并在GC运行期间移动它。但是,该对象不包含数据;相反,它保持大小和指向保存值的内存块的指针。该内存块未使用GC分配,因此不会移动。
+------------------------+
| GC-managed Blob object |
+------------------------+ +------------------------+
| Elements |----->| Non-GC-managed memory |
+------------------------+ | (this bit is passed to |
| Size | | native code) |
+------------------------+ +------------------------+
你是否应该依赖这个是一个棘手的问题。一些考虑:
“在其上放置特征”的问题在于,至少在JVM上的决定似乎需要在分配存储数据的存储器时做出决定。在这种情况下,便携式解决方案可能不允许将现有的Buf
/ Blob
标记为这样。也许更好的方法是I / O-ish要求提供类似CArray
的东西,以便通过将数据放在“正确类型的存储器”中来实现零拷贝。这可能是一个合理的功能请求。