How to bind a window library (in C) to Haskell?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

How to bind a window library (in C) to Haskell?

Brian Hulley
Hi -
I'd like to be able to use Haskell for the project I'm working on but the
problem is that I've already written a lot of code for a nice GUI using
DirectX in Visual C++.

I thought it might be possible to make up some kind of simple API for it
which I could call from Haskell, so I started with the following simple
Haskell module to try and see if I could understand the FFI:

           module Main where

           data Window = Window_Edit | Window_List | Window_Tree
           data Layout = Layout_Left | Layout_Right

           type Callback = () -> Bool

           foreign import ccall gui_init :: [(Window, Layout, Callback)] ->
IO ()

           main = gui_init [(Window_Edit, Layout_Left, \_->True)]

Of course my "init" function is far too simple, but I was thinking this
captures the essence of the kinds of things that would need to be passed to
the C++ code ie a list of windows and call back functions etc.

However I've immediately run into a major problem. When I try to compile
with ghc -fglasgow-exts --make main.hs I get an error: "unacceptable
argument type in foreign declaration..."

My questions are:

1) Does this mean that the FFI can only pass Int, Char etc and not user
defined data types or compound data types?

2) I'm also really confused by the different kinds of pointers available,
and how to safely store a function closure in some C data structure, and how
to use this to call the function from within C and access the result safely

3) When does GHC do garbage collection? Is the garbage collection done in
the same thread as the executing program? Does GHC run a normal Haskell
program using multiple threads? Would I need to link my C DLL with a
multithreaded version of the C runtime to avoid problems?

Alternatively, has anyone managed to use DirectX or COM from within a
Haskell program? (because then I could perhaps rewrite all my gui code from
scratch in Haskell...) (I'm loathe to switch to OpenGL because OpenGL is
very poorly supported on windows - a default WinXP installation does not
come with hardware accelerated OpenGL drivers, afaik, and also I can't find
any documentation on the Haskell OpenGL bindings except the Haddock type
signatures which are just not nearly enough to understand how to use it, and
some out of date docs)

Thanks, Brian.

_______________________________________________
Glasgow-haskell-users mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Reply | Threaded
Open this post in threaded view
|

Re: How to bind a window library (in C) to Haskell?

Esa Ilari Vuokko
On 2/27/06, Brian Hulley <[hidden email]> wrote:
Hi

[snip]
> 1) Does this mean that the FFI can only pass Int, Char etc and not user
> defined data types or compound data types?

Yes.  The idea is that instead of pointers/references you have
Ptr a, and instance Storable a that provides marshalling between
haskell and C.  Very often you actually get two sets of bindings,
"raw", exact C-signatures, enums as variables etc, and higher
level, implemented on top of the raw-level, where you have data
and class declarations to simulate usefull parts of foreign C
hierarchy - your code looks more like the higher-level part.

> 2) I'm also really confused by the different kinds of pointers available,
> and how to safely store a function closure in some C data structure, and how
> to use this to call the function from within C and access the result safely

Ptr is basically plain old c-pointer.  Haskell, however, just sees it
as an address with typetag, and accessing object requires marshalling,
typically through Storable-class.

FunPtr is basically plain c-function pointer.

To create FunPtr's, you need to declare and use ffi-wrappers.
Something like (taken from Win32-packages Graphics.Win32.Window):

type WindowClosure = HWND -> WindowMessage -> WPARAM -> LPARAM -> IO LRESULT

foreign import ccall "wrapper"
  mkWindowClosure :: WindowClosure -> IO (FunPtr WindowClosure)

If you are resource-handling savvy, you need to call freeHaskellFunPtr after
you finish using that FunPtr.

Of course, plain C-function pointers are naturally FunPtr's, and require no
freeing.

> 3) When does GHC do garbage collection? Is the garbage collection done in
> the same thread as the executing program? Does GHC run a normal Haskell
> program using multiple threads? Would I need to link my C DLL with a
> multithreaded version of the C runtime to avoid problems?

C and ghc memory management are not tied together.  You should use your
own functions in C to release any memory allocated in C.  As far as I
understand, haskell gc only happens when you are executing haskell.

> Alternatively, has anyone managed to use DirectX or COM from within a
> Haskell program? (because then I could perhaps rewrite all my gui code from

I have written, but not published, experimental DirectX9.D3D bindings.
I plan to publish it at some point, but it's pretty hairy at the moment
(and incomplete, not all of D3D is done, also no docs etc).   I don't
have time to work on them right now, so you might need to put quite
an effort in if you wish to use them.  (And there is no DirectX 7
bindings, if you are using that for 2D.)

Using COM might be pretty obvious if you are willing to play around
with IDL and HaskellDirect.  (There is no IDL files for DirectX9, so I
used various hacks and COM c-interface)  Or ofcourse, manually
reading COM vtables isn't that hard, either.

There are various other things one can do, also.  Like using C-interface
and thin c-wrapper funcionts (COM interface c-parts are usually
preprocessor macros, so linking them in haskell isn't really convient).
Or C++. of course, but then

> scratch in Haskell...) (I'm loathe to switch to OpenGL because OpenGL is
> very poorly supported on windows - a default WinXP installation does not
> come with hardware accelerated OpenGL drivers, afaik, and also I can't find
> any documentation on the Haskell OpenGL bindings except the Haddock type
> signatures which are just not nearly enough to understand how to use it, and
> some out of date docs)

If you are comfortable reading OpenGL spec, the haddock documentation should
be pretty simple to follow.

HTH,
-Esa
_______________________________________________
Glasgow-haskell-users mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Reply | Threaded
Open this post in threaded view
|

Re: How to bind a window library (in C) to Haskell?

Brian Hulley
Hi Esa!

Thanks for the very detailed and clear explanation! I was going to wait till
I'd implemented a simple example of passing/calling a function closure to
post a reply but I've wasted all day just trying to think up a good name for
my graphics library! :-)

Regarding DirectX bindings, if you've not already done so you may be
interested to see how the DirectX9 .NET api is structured. Certainly when I
wrote a small graphics program in C# a year or so ago I was quite impressed
by the way the DX9.NET api managed to hide a lot of the mess that you have
to deal with in the C/C++ api such as keeping track of resources that
suddenly disappear and dealing with reset properly.

It looks like I won't need to go to such a low level though for my api - I
imagine my call back functions will be implemented easily by using a FunPtr
to something which returns a suitable monadic type which will keep track of
the state of the app's 'document' and be combined with the IO monad in some
way.

Also thanks for pointing out the existence of the Win32 bindings. Also I
noticed that a Haskell version of the ObjectIO library was hiding in my GHC
installation too, so this will be a further useful source of ideas for how
to structure my api.

Best regards,
      Brian.

_______________________________________________
Glasgow-haskell-users mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users