在阅读了几个wiki和stackoverflow QA之后,我想到了如何将GC分配的内存的标记/通过区域传递给C库的问题。大多数处理FFI的库似乎首先分配内存,将值复制到其中,然后将其包装为Ptr类型。问题是要保证在C库中花费时间时不会移动或释放内存。
假设我有一个类型为Text的值myInput,并且我想用C做零拷贝FFI。我有什么选择?
到目前为止,我发现了以下内容:
https://wiki.haskell.org/Foreign_Function_Interface#Pointers_to_Haskell_data
在某些情况下,您可能想给外来代码一个不透明的对Haskell值的引用,稍后再检索它。您需要确保在提供值和检索值之间没有收集到该值。精确创建了稳定的指针可以做到这一点。您可以将值包装到StablePtr中并将其提供给外来代码(StablePtr是可编组的外来类型之一)。
与某些人交谈后。他们告诉我,不应取消引用StablePtr。并且主要用于传递void *。另一方面,维基说它适用于此目的,并且此答案也表示相同的https://stackoverflow.com/a/10900699/1833322
有关StablePtr的更多信息:
https://www.well-typed.com/blog/2018/05/ghc-special-gc-objects/
在每个GC稳定指针更新后,指向它们在GC之前指向的Haskell对象的新位置
https://hackage.haskell.org/package/base-4.11.1.0/docs/Foreign-StablePtr.html#t:StablePtr
稳定指针是对Haskell表达式的引用,该引用保证不会受到垃圾回收的影响,即,在垃圾回收期间,既不会释放它,也不会更改稳定指针本身的值(可以重新定位普通引用)在垃圾回收期间)。因此,可以将稳定的指针传递给外来代码,该代码可以将其视为对Haskell值的不透明引用。
我以为我可以用newStablePtr http://hackage.haskell.org/package/base-4.12.0.0/docs/Foreign-StablePtr.html#v:newStablePtr包装我的Text并完成它。我不明白StablePtr现在的情况如何。如果我可以为此目的使用或不使用它。如果不是的话,它的实际用途是什么。
然后使用ByteString固定内存https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC/Pinned
还有固定的ByteArray http://hackage.haskell.org/package/primitive-0.6.2.0/docs/Data-Primitive-ByteArray.html#g:2
使用ByteString和ByteArray的一件事就是,IO库经常提供它们自己的数据结构,因此必须首先将数据复制到INTO ByteString / ByteArray中,这是我首先要避免的事情。
也许有一些(不安全的?)强制转换功能?
这似乎是一个简单的问题,因为GC似乎已经能够将内存的某些部分标记为“不要移动”(固定)。我可以在结构上调用以切换此标志的功能吗?还是为此用例提供了其他合适的功能?