c2hs seems to ignore the types I give it when generating foreign import declarations

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? - Cale

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.

On 11/12/05, Manuel M T Chakravarty
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.
Hi, I wanted to use the existing types so as to have compatibility with any other libraries which might use them. It would be a shame if every Haskell binding to an X library had different, incompatible versions of the X types, and thus they couldn't be used together. I managed to get something which worked, but I've been distracted by other random things lately. Perhaps I'll come back to it now :) The binding to Ecore and Evas sounds good, I was hoping to eventually bind the whole EFL. - Cale I would like to do bindings on Ecore an

Cale Gibbard:
On 11/12/05, Manuel M T Chakravarty
wrote: 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').
I wanted to use the existing types so as to have compatibility with any other libraries which might use them. It would be a shame if every Haskell binding to an X library had different, incompatible versions of the X types, and thus they couldn't be used together.
The darcs version of c2hs darcs get --partial http://www.cse.unsw.edu.au/~chak/repos/c2hs/ now permits the use of a `nocode' keyword at the end of a pointer hook. This suppresses the generation of the type declaration, so you can do {#pointer *Display as Display newtype nocode#} to get what you want. Let me know if there are any problems. Manuel

On Monday 12 December 2005 02:17, Manuel M T Chakravarty wrote:
The darcs version of c2hs
darcs get --partial http://www.cse.unsw.edu.au/~chak/repos/c2hs/
now permits the use of a `nocode' keyword ...
Hello not directly related, but are there any plans to add the (still?) missing 'enum define' hooks in teh near future? Ben

Benjamin Franksen:
On Monday 12 December 2005 02:17, Manuel M T Chakravarty wrote:
The darcs version of c2hs
darcs get --partial http://www.cse.unsw.edu.au/~chak/repos/c2hs/
now permits the use of a `nocode' keyword ...
Hello
not directly related, but are there any plans to add the (still?) missing 'enum define' hooks in teh near future?
This feature is still on the todo list, but it's hard to say when I'll get around to implementing it. One reason why enum define is not so high on the top of the list is that there is a simple workaround. Here is an example: -=- myheader.h -=- /* A #define enum */ #define THIS 1 #define THAT 2 -=- MyBinding.chs -=- import C2HS #c enum ThisThat { This = THIS, That = THAT }; #endc {#enum ThisThat {}#} In other words, you can use inline C in .chs files to define a C enum that an enum hook can process. This is not that much more verbose as what you would have to write in an enum define hook anyway (as you need to enumerate all macro names that contribute to the enum anyway). Moreover, I am always grateful for patches that improve c2hs. Cheers, Manuel
participants (3)
-
Benjamin Franksen
-
Cale Gibbard
-
Manuel M T Chakravarty