Function call when deleting an object in Haskell

I am writing a Haskell wrapper for a C ++ class. I decided to present it as a Haskell data structure containing a pointer (Foreign.Ptr) to an instance of a class in C ++. Something like that.

In 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(); } 

In 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 

The problem is that I don’t know how to properly implement the removal of MyClass. At some point, the Haskell garbage collector will delete the MyClass object, but it will not cause the release of MyClass * memory in C ++. How to fix it?

I know ForeignPtr , but uses IO monad, which is not satisfactory because I want the packed data structure to behave exactly like a normal Haskell data structure, without the need for explicit allocation / deallocation of memory or IO monads.

+8
c ++ garbage-collection haskell ffi
source share
1 answer

"he uses the IO monad, which does not satisfy, because I want the packed data structure to behave exactly like a normal Haskell data structure"

Of course, yes, but, unfortunately, this is really impossible. Foreign "functions" can always do funny things that may not be possible in Haskell; the type system is not able to look there and prevent it.

This dilemma is the only (!) Reason we have unsafePerformIO , and really yours, is a good example of a valid application for this thing.

I haven't done it myself yet, but your code should look something like this:

 extern "C" void cpp_delete_MyClass(MyClass* obj) { delete obj; } 
 foreign import ccall "cpp_new_MyClass" cppNewMyClass :: IO (Ptr ()) foreign import ccall "&cpp_delete_MyClass" cppDeleteMyClass :: FunPtr (Ptr () -> IO ()) data MyClass = MyClass (ForeignPtr ()) mkMyClass :: MyClass mkMyClass = unsafePerformIO $ do newObj <- cppNewMyClass fPtr <- newForeignPtr cppDeleteMyClass newObj return $ MyClass fptr 

I'm not quite sure about these FunPtr s, I hope someone comments on this ...

+7
source share

All Articles