在Haskell中删除对象时调用函数 我正在编写一个C++类的Haskell包装器。我决定把它表示为一个包含指针(Fiel.pTR)的Haskell数据结构,它是C++中的类实例。差不多吧
在C++中:在Haskell中删除对象时调用函数 我正在编写一个C++类的Haskell包装器。我决定把它表示为一个包含指针(Fiel.pTR)的Haskell数据结构,它是C++中的类实例。差不多吧,c++,haskell,garbage-collection,ffi,C++,Haskell,Garbage Collection,Ffi,在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(); } 在哈斯克尔: Data MyClass = MyCla
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();
}
在哈斯克尔:
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垃圾收集器在某个时候会删除MyC类对象,但是它不会触发MyClass在C++中释放的内存。我该如何解决这个问题
我知道,但它使用了IO
monad,这并不令人满意,因为我希望包装的数据结构与正常的Haskell数据结构完全一样,而不需要显式分配/释放内存或IO
monad
“它使用IO
monad,这并不令人满意,因为我希望包装的数据结构与正常的Haskell数据结构完全一样”
当然,但不幸的是,这不太可能。外国的“功能”总是可以做一些有趣的事情,这在哈斯克尔是不可能的;类型系统无法查看并阻止它
这一困境是我们拥有unsafePerformIO
的唯一(!)原因,事实上,您的应用程序就是一个很好的例子
我自己还没有这样做,但您的代码应该如下所示:
extern "C" void cpp_delete_MyClass(MyClass* obj) {
delete obj;
}
foreign import ccall“cpp\u new\u MyClass”cppNewMyClass::IO(Ptr())
外部导入ccall“&cpp_delete_MyClass”cppDeleteMyClass::FunPtr(Ptr()->IO())
数据MyClass=MyClass(ForeignPtr())
mkMyClass::MyClass
mkMyClass=unsafePerformIO$do
你的班级没有副作用吗?如果不是,因为它在C++中是常见的,你必须使用<代码> IO < /Cord>单元格,或者小心地确保你将纯接口暴露给它。这或者失去引用的透明度,这在Haskell中是一个致命的罪过,因为这将使程序的行为几乎无法预测,特别是当优化器假设它重写代码时。@chi是的,它没有副作用。我在ForeignPtr
上使用unsafePerformIO
想到了这样的解决方案,但我不确定它是否能正常工作。如果你是,你能解释一下在那个方法后面的场景是什么吗?@每次WWWT(代码< > MKMyCype < /Cord>)被评估(应该只有一次,但不依赖于此)分配一个C++对象,用一个附加的终结器创建一个Haskell值,并返回纯的值。当垃圾收集其中一个值时,将运行终结器(cppDeleteMyClass
)。声明cppdetemyclass
的正确方法是foreign import ccall“&cpp\u delete\u MyClass”cppdetemyclass::FunPtr(Ptr()->IO())
(添加(&D))。你可能应该修正你的答案。如果你想保证cppNewMyClass
只被调用一次,你应该在mkMyClass
上加上一条NOINLINE(尽管在这种情况下OP可能不需要这样的保证)。