[Haskell-cafe] c2hs seems to ignore the types I give it when
generating foreign import declarations
Manuel M T Chakravarty
chak at cse.unsw.edu.au
Sun Dec 11 09:50:43 EST 2005
Cale Gibbard:
> Hello, I've just started writing bindings to the Enlightenment
> Foundation Libraries, using c2hs. I've run into the following problem
> with the types in the foreign import declarations generated.
>
> In Imlib2.h, there is a function prototype:
> int imlib_get_visual_depth(Display * display, Visual * visual);
>
> In Imlib.chs, I have (among other things)
> import qualified Graphics.X11.Xlib.Types as Xlib
> -- ...
> {# fun imlib_get_visual_depth as getVisualDepth { id `Xlib.Display',
> id `Xlib.Visual' } -> `Int' #}
>
> I run:
> c2hs -k /usr/local/include/Imlib2.h Imlib.chs
>
> and in the resulting Imlib.hs, I get:
>
> --- this part is correct:
> getVisualDepth :: Xlib.Display -> Xlib.Visual -> IO (Int)
> getVisualDepth a1 a2 =
> let {a1' = id a1} in
> let {a2' = id a2} in
> getVisualDepth'_ a1' a2' >>= \res ->
> let {res' = cIntConv res} in
> return (res')
>
> --- this part is not:
> foreign import ccall safe "Imlib.h imlib_get_visual_depth"
> getVisualDepth'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO CInt)))
>
> Why did it choose the type Ptr (), when I gave the type Xlib.Display?
> I could do an additional cast, but it will get tedious, as I have a
> lot of functions to import, and there shouldn't be any need for it
> anyway. As this is, it doesn't typecheck at all. If by hand, I change
> it to read:
>
> foreign import ccall safe "Imlib.h imlib_get_visual_depth"
> getVisualDepth'_ :: Xlib.Display -> Xlib.Visual -> IO CInt
>
> (which is what I expected it to produce in the first place) then it
> works as expected.
>
> Am I making a grievous error, or is this a bug/lack of a feature?
You need to tell c2hs to what Haskell type a C pointer type maps before
it can generate the right signature for the import declaration. This is
done using a pointer hook:
http://www.cse.unsw.edu.au/~chak/haskell/c2hs/docu/c2hs-3.html#ss3.10
In your case, you would usually do
{#pointer *Display as Display newtype#}
However, when you use this form, c2hs will generate the newtype
declaration for you that you import from `Graphics.X11.Xlib.Types' (and
you would have to cast between your version of `Display' and that of
`Xlib').
Are you actually going to use functions from `Graphics.X11.Xlib' on
these types or did you just want to use the existing types because it is
more elegant? It is a awkward to use existing types that have *not*
been generated by c2hs in that way at the moment. However, it should be
quite easy to extend c2hs to enable this quite easily if it is
important.
Manuel
PS: I started a binding of Ecore and Evas a while ago. Still
incomplete, but if you meant to do these, too, then we should maybe
exchange code instead of duplicating work.
More information about the Haskell-Cafe
mailing list