From: Manuel M T C. <ch...@cs...> - 2005-08-23 14:17:35
|
Axel Simon: > Ok, I squeezed your answers together. > > On Sun, 2005-08-21 at 23:22 +1000, Manuel M T Chakravarty wrote: > > Axel Simon: > > > On Thu, 2005-08-18 at 16:39 +0100, Duncan Coutts wrote: > > > > On Thu, 2005-08-18 at 15:45 +0100, Axel Simon wrote: > > > > > > > > > On Thu, 2005-08-18 at 14:55 +0100, Duncan Coutts wrote: > > > > > > > > > > which is essentially the same as the with* function, but used > > > > > > automatically and inlined at the call site. > > > > > > > > > > It also doesn't pollute the name space. This is more severe that it may > > > > > seem at first. In Gtk2Hs we often {#import #} modules, so that c2hs know > > > > > about the c2hs type declarations in the module. If we were to switch to > > > > > with* functions, we would also have to add these with* functions to the > > > > > export list, depending on weather we use the type somewhere else or not. > > > > > Furthermore we should then hide all these with* functions in Gtk.hs. > > > > > This imposes quite a significant maintenance problem with no apparent > > > > > benefit. > > On Sun, 2005-08-21 at 22:58 +1000, Manuel M T Chakravarty wrote: > > Yes, that's a good point, but what do you do when a ForeignPtr is > > returned as a result? What finalizer do you attach? > > I distinguish return values from arguments. Return values are always > non-wrapped, pure pointers or basic data types. We stick on the > function to free the ForeignPtr and the newtype constructor afterwards. > Automating that is much more involved. To be honest, I am not really keen on an asymmetric approach. This is why we dropped native marshalling of ForeignPtrs in the FFI spec (and that wasn't only my decision, but shared by everybody who participated in the discussion). > [here I admitted that exporting the newtype constructors is no > different than exporting the with* functions.] So, maybe its better to use explicit with functions for call hooks after all. In fun hooks, it's a different story. Having the with functions as default marshallers saves code and there is a standard mechanism to define function specific handling of both argument and result marshallers. > > > b) The inlined version is more flexible when it comes to extensions. We > > > could for example have a tag like "{#call blah bare(PangoFont)#}" which > > > would then let me pass a "Ptr PangoFont" to the function, instead of > > > forcing me to create a ForeignPtr which I'm throwing away immediately > > > afterwards. I just came across this situation. Even nicer, we could add > > > a tag "{#call blah maybe(PangoFont)#}" which takes a "Maybe PangoFont". > > > c2hs could then insert a case distinction to pass a nullPtr to the > > > function if the argument is Nothing. Note that we can't do this at the > > > moment and we have to use the ugly and inefficient (mkPangoFont > > > nullForeignPtr) to pass a Maybe value. In fact, the only reason we have > > > nullForeignPtr is that we can't tell c2hs that we occasionally want to > > > pass a Ptr instead of a ForeignPtr. If we'd stick to the with* approach, > > > we would loose the ability to override the default marshaling for a > > > specific type. > > > > I understand why you like this, but what I am concerned about is that > > you now start to replicate the functionality of fun hooks (which I guess > > were added after you had already done all the design for Gtk2Hs). > > I think they were indeed added after I forked c2hs off. I've just looked > at the documentation of the fun hook. I admit that having a maybe(..) > option is like marshaling magic that looks like it should be in the fun > hook. However a nullPtr can only be passed by c2hs; we always need to > pass a newtype-wrapped nullForeignPtr to the function. Hence it seems > that the nullPtr issue arises as soon as you allow clever things in the > {#pointer #} hooks. > > Similarly, the issue of sometimes passing a PangoFont as (Ptr PangoFont) > instead of the newtype-wrapped ForeignPtr seems to be the result of a > more expressive {#pointer #} hook. We need exceptional cases e.g. when > we bind a function to free a PangoFont (in pre ghc-6.00) which naturally > takes a bare pointer. Yes, but the idea of the call hooks was really that they just automate the call and none of the argument and result marshalling. In contrast, fun hooks do argument and result marshalling (and internally use call hooks to do the actual FFI call). I fully understand that when you made your design, c2hs didn't support all this, so you had to find a different solution, but it seems a bit awkward to add some fun hook functionality to call hooks in the current c2hs. I don't know what your code generators exactly automate, but would it be feasible to generate fun hooks? (I'd be happy to add more intelligence to the default fun hook marshalling if you need that.) > > > I appreciate your attempt to mediate, but the more I think about the > > > Gtk2Hs approach vs. the with* approach, the more I like the former. It > > > shouldn't be too hard to fix it for type synonyms. I could try it this > > > week end, but it really only makes sense if Manuel is happy with it > > > (since Gtk2Hs doesn't use plain type synonyms). > > > > Sorry that my reply was too late. I understand why you like you > > approach, and I sympathise with that, but one problem with changing the > > default behaviour of c2hs is that it would break everybody else's code. > > So, at best, we could make the alternate behaviour an option. > > So what breaks are ForeignPtr hooks, I assume. So when I say > > {#pointer *PangoFont foreign newtype#} > pangoFontGetSize :: PangoFont -> IO Int > pangoFontGetSize pf = > liftM fromIntegral $ {#call unsafe pango_font_get_size#} pf > > our version of c2hs generates: > > newtype PangoFont = PangoFont (ForeignPtr PangoFont) > pangoFontGetSize pf = liftM fromIntegral $ > (\(PangoFont arg1) -> withForeginPtr arg1 $ \arg1 -> > pango_font_get_size arg1) pf > > ... pango_font_get_size :: Ptr PangoFont -> IO CInt ... > > your version generates: > > newtype PangoFont = PangoFont (ForeignPtr PangoFont) > withPangoFont (PangoFront for) = withForeignPtr for > > pangoFontGetSize pf = liftM fromIntegral $ > pango_font_get_size pf > > and in your version I was meant to use withPangoFont pf $ \pfPtr -> ? > If I got this right, then I see how code can be broken. But I think the > abstraction that c2hs gives is not quite right in both cases. In your > version, you let the user declare special treatment for PangoFont but > don't actually honor it. In our case we don't honour return values since > they are always (Ptr PangoFont), just like your arguments (and return > values). The idea behind call hooks is to not do anything about marshalling. It's just the plain function that's automated. All c2hs does is provide the necessary marshalling functionality (in form of the with function), but it's up to the user to do the actual argument marshalling. I think that's a consistent view. > One could fix the pointer hook by specifying the finalizer and let c2hs > automatically create the corresponding code. I don't really like that, > though, since sometimes things are too complicated to be left to c2hs. I agree. > > BTW, I just had a look at c2hs' source and unfortunately our two source > > trees have diverged here. I guess when I added fun hooks, I changed the > > type of PointerMap already, so a patch from your tree wouldn't apply > > cleanly. > > Can you recover what has changed? Your darcs repository does not reveal > any information on c2hs/chs/CHS.hs. Did you get the repository with --partial? darcs changes c2hs/chs/CHS.hs gives me the history back to April 2001. (I converted the CVS to darcs with taylor.pl.) Cheers, Manuel |