【发布时间】:2015-08-31 14:05:11
【问题描述】:
我正在为 C++ 类编写 Haskell 包装器。我决定将其表示为包含指向 C++ 中类实例的指针 (Foreign.Ptr) 的 Haskell 数据结构。类似的东西。
在 C++ 中:
class MyClass {
public:
double my_method();
// ...
};
extern "C" MyClass* cpp_new_MyClass() {
return new MyClass();
}
extern "C" double cpp_my_method(MyClass *obj) {
return obj->my_method();
}
在 Haskell 中:
Data MyClass = MyClass (Ptr ())
foreign import ccall "cpp_new_MyClass" cppNewMyClass :: Ptr ()
foreign import ccall "cpp_my_method" cppMyMethod :: Ptr () -> Double
mkMyClass :: MyClass
mkMyClass = MyClass cppNewMyClass
myMethod :: MyClass -> Double
myMethod (MyClass ptr) = cppMyMethod ptr
问题是,我不知道如何正确实现 MyClass 删除。在某些时候,Haskell 垃圾收集器会删除 MyClass 对象,但不会触发 C++ 中的 MyClass* 内存释放。我该如何解决?
我知道ForeignPtr,但它使用IO monad,这并不令人满意,因为我希望包装的数据结构与普通的 Haskell 数据结构完全一样,而不需要显式分配/释放内存或IO monads。
【问题讨论】:
-
你的课堂副作用免费吗?如果不是,因为它在 C++ 中很常见,您必须 使用
IOmonad,或者小心 确保向它公开一个纯接口。或者失去引用透明度,这在 Haskell 中是一个致命的罪过,因为它会使程序的行为几乎无法预测,尤其是当优化器假设它重写你的代码时。 -
@chi 是的,没有副作用。
标签: c++ haskell garbage-collection ffi