
On 12/13/06, Brandon Moore
It looks to me like the C code could make your program segfault from a type missmatch, if it gets a handle from instantiating one descriptor, and tries to run it from another.
Well, the C code could even provide (by error or at will) any pointer value which could mismatch or not. C is potentially dangerous by definition and there is no way to cope with that whatever we export from Haskell. This is just a particular case of that major problem, in which we use a instance handle.
Building code which can fail that way hopefully requires unsafeCoerce!
Any haskell code which receives a C pointer is likely to suffer from the type-mismatch segfault problem you mentioned above. The purpose of using unsafeCoerce in my code is to allow me to pack some polymorphic values in a list as if they ware homogeneous. I don't see how unsafeCoerce would help me with a type mismatch.
I think Udo's code is the best way to go, if it solves your problem. Udo's code is equivalent to code similar to yours but defined around the existential type
data Descriptor = forall hd . Descriptor { -- create a new instance and return its handler instantiate :: InstanceInitData -> hd, -- Run and return a new handler run :: hd -> IO hd}
Hiding the hd parameter breaks the C-exported cRun function.
Then observing that because hd is hidden you can only use an hd by passing it run, so you might as well wrap it up in that Runner type.
Which yet again, requires splitting Descriptor in two.
If you want to be able to define several Descriptors over the same type hd, and ....
Different descriptors are allowed to have different handlers (void *) in C. That's a precondition, and furthermore, the source of my modelling problem and this thread :)