Creating a Haskell application with a .NET GUI - haskell

I'd like to create a Haskell app with a .NET gui. I'd like to use cabal as my build tool to take advantage of it's package management etc. I think the Haskell part should be the executable that calls into the .NET code as:
This avoids having to manually initialize the Haskell RTC as described here: http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/win32-dlls.html
cabal cannot easily produce Windows dlls: http://www.haskell.org/haskellwiki/Cabal/Developer-FAQ#Building_DLLs__with_Cabal
I've found it fairly easy to create a Haskell executable that call's .NET using hs-dotnet, but I also need my GUI code to call back into Haskell. I was hoping to achieve this using Haskell's "foreign export" command, then call this exported function via .NET native interop. However the "foreign export" function doesn't seem to create an entry point in the executable, I can't see the entry point when I do dumpbin /EXPORTS on the resulting executable. I'm not sure whether this is because GHC only create's entry point's when creating a dll via the -shared switch or whether cabal add a flag that suppresses entry point creation.
So I guess the question is how do I force GHC to create entry points in my Windows executable? Or would I be better using a .NET executable going though the necessary steps to create a Haskell dll with cabal and manually initializing the Haskell RTC?

I usually solve this by passing callbacks as function pointers. For example, I have an app where pressing a button needs to call back into Haskell (I'm using Cocoa, but except for the names it's very similar).
First, I subclass an NSButton object, and give my new ButtonC class a private member of type void(*onClickCallback)(). I also declare a function void setClickCallback(ButtonC *button, void(*callback)()); Implement your subclass so that whenever the button is clicked, the function pointer is called. In .Net, there may be a clever way to do this with delegates (it's been a while since I've used .Net).
Next, my Haskell binding looks like this (some code omitted):
module Foreign.Button where
data ButtonObj
type ButtonPtr = ForeignPtr ButtonObj
foreign import ccall unsafe "setClickCallback"
c_setClickCallback :: Ptr ButtonObj -> FunPtr (IO ()) -> IO ()
foreign import ccall "wrapper"
makeClickCallback :: IO () -> IO (FunPtr (IO ()))
buttonSetCallback :: ButtonPtr -> FunPtr (IO ()) -> IO ()
buttonSetCallback btn cb =
withForeignPtr btn $ \p -> c_setClickCallback p cb
buttonNew :: IO ButtonPtr
buttonNew = ...
Now Haskell data of type IO () can be wrapped in a FunPtr and passed into the GUI with buttonSetCallback. Whenever the button is pressed, the IO () action is performed.
createButton :: IO ButtonPtr
createButton = do
btn <- buttonNew
let buttonClicked = print "The button was clicked!"
btnCallback <- makeClickCallback buttonClicked
buttonSetCallback btn btnCallback
return btn
One thing to beware of with FunPtrs is that they aren't garbage collected. You need to manually deallocate them when you've finished or you'll have a memory leak. A good practice is to never share FunPtrs, and also never retain references to them on the Haskell side. That way your object can free the FunPtr as part of its cleanup. This requires yet another callback into Haskell (a freeFunPtr function) that should be shared between all your objects and is itself only freed when your executable terminates.

Related

How do I render a Cairo drawing to a printer in Haskell gtk2hs

I'm using the GTK3 build of gtk2hs. I have a Cairo drawing in the Render monad and I want to send it to a printer.
I see that there is a Surface type which encapsulates the Cairo back end. For example it is possible to create an SVG surface using withSVGSurface, and there are similar functions for PDF, Postscript and PNG. Once you have a Surface you can apply a Render action (i.e. actually draw on it) using renderWith. This is perfectly straightforward, and I can see how to use these functions to export drawings as files.
However printing does not seem to work this way. The printOptDrawPage signal provides its callback with a printContext value. This has a function printContextGetCairoContext which returns a Cairo Context. However the library documentation doesn't have an entry for this Context type, and I can't find any functions that use it.
It looks like there ought to be printContextGetSurface function, or else a way to convert a Context into a Surface. Am I missing something?
Hah, whoops, that's embarrassing! It seems the bindings are just a little incomplete in this department.
Luckily it should be pretty easy to update them. Taking a look at the definition of the Render monad:
newtype Render m = Render { runRender :: ReaderT Cairo IO m }
We can see that the Cairo object you get from printContextGetCairoContext is just what you need to do something useful with a Render action. The implementation of the renderWith function gives you a clue about what cleanup actions you should take:
renderWith surface (Render m) = liftIO $
bracket (Internal.create surface)
(\context -> do status <- Internal.status context
Internal.destroy context
unless (status == StatusSuccess) $
fail =<< Internal.statusToString status)
(\context -> runReaderT m context)
I think one of two patches would be sensible here:
Expose a renderWith-alike that consumes a Cairo. Let the user connect up printContextGetCairoContext with the new renderWith-alike.
Don't expose printContextGetCairoContext at all; replace it with
printContextRender :: PrintContextClass self => self -> Render a -> IO a
and have printContextRender merge the call to printContextGetCairoContext with the renderWith-style cleanup.
I like option (1) for its clean backwards-compatibility story; but I like (2) a lot better from the API-design side of things. Since this module probably hasn't seen much use for the reasons you're describing, I'd lean towards patch (2).
I'd also note that you may want to look into the gtk documentation a bit to check whether the Cairo context cleanup is somebody else's responsibility (the PrintOperation's, for example).
Happy hacking!

Listening for "owner change" events for the clipboard in gtk2hs. How to set up?

Using Gtk2Hs, I want to set up a callback to listen for "Owner change" events for the clipboard.
I can find out if this is supported by the X server by querying:
display <- fmap fromJust displayGetDefault
canBeNotified <- displayRequestSelectionNotification display selectionPrimary
It should be straight forward to do like this in C:
GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
g_signal_connect(clipboard, "owner-change",
G_CALLBACK(handle_owner_change), NULL);
I see that callbacks in Gtk2Hs are set up like this:
<widget> `on` <event> $ <action>
Problems
I cannot find any OwnerChangeEvent. Graphics.UI.Gtk.Gdk.EventM does only provide functions of type EventM to query the owner change events.
on from System.Glib.Signals needs an associated widget takes any object and an event associated to that object (on :: object -> Signal object callback -> callback -> IO (ConnectId object). If I have understood X correctly, it should not be necessary to have a window to listen for this event.
Either I have misunderstood how to wrap this together, or I have reached upon a yet not implemented part of gtk in Gtk2Hs.
I therefore looked at the definition of keyPressEvent which looks like this:
keyPressEvent :: WidgetClass self => Signal self (EventM EKey Bool)
keyPressEvent = Signal (eventM "key_press_event" [KeyPressMask])
So, I tested by simply adding a definition for ownerChangeEvent in gtk like keyPressEvent, but subsituted "key_press_event" for "owner_change_event".
That did not work as I got a runtime error about not finding the event. Naturally.
Any ideas on how to properly listen for "owner change" events in gtk if possible?
You're right that this is not implemented at the moment. Adding it shouldn't be too involved, and might be a fun project if you're looking to get into gtk2hs development. You'll want to add a new constructor to the Event type, together with a descriptive type alias like type EventOwnerChange = Event. You will need to extend marshalEvent to handle this new kind of event, and there may be an unmarshalEvent hanging around though I can't remember.
Once that's all done, it should be pretty easy to connect to the appropriate signal using the connect_* family of functions (which are for gtk2hs internal use only and therefore are not exposed in the API). From the documentation for the owner-change event, you will probably need to use something like Signal (connect_OBJECT__NONE "owner-change").
It may also be necessary to add to the EventMask type, though I'm not confident -- test it out and see.

Bind splice to tag in Heist

I want to use a website as a working example in order to help learn Haskell. I'm trying to follow the Heist tutorial from the Snap website, and display the result of a factorial function in a web page.
I can get the example function defined "server side" without the compiler complaining, but I cannot figure out how to bind the function to a tag which I can then place into the HTML. Specifically, this part works fine (in, say, Site.hs):
factSplice :: Splice Snap
factSplice = do
input <- getParamNode
let text = T.unpack $ X.nodeText input
n = read text :: Int
return [X.TextNode $ T.pack $ show $ product [1..n]]
But the really important part - how to evaluate this function as part of a web page (such as how to bind it to a tag like < fact />) - is cryptic. The instructions say to drop:
bindSplice "fact" factSplice templateState
somewhere in the code. But this alone is not sufficient. This statement is not an expression (stuff = bindSplice...), so it is not clear how or where to put it in the code. Moreover, it is not at all clear where "templateState" is supposed to come from. It almost seems like "templateState" is supposed to be a placeholder for default values like emptyTemplateState or defaultHeistState, but these both appear to have been deprecated years ago, and the latest version of Heist (0.14) does not recognize them.
MightyByte has commented on this kind of question several times in 2011, but the answers all gloss over exactly the confusing part, i.e. how to actually get data into a web page. Can anyone help?
-- UPDATE --
Thank you very much, mightybyte! Your explanation and some cursory poking around in the source code cleared up a lot of confusion, and I was able to get the factorial example from the Snap website tutorial working. Here is my solution - I'm a complete n00b, so apologies if the explanation seems pedantic or obvious.
I more or less used the addConfig approach that mightybyte suggested, simply copying the implementation of addAuthSplices from SpliceHelpers.hs. I started with the default project via "snap init", and defined a function addMySplices in Site.hs
addMySplices :: HasHeist b => Snaplet (Heist b) -> Initializer b v ()
addMySplices h = addConfig h sc
where
sc = mempty & scInterpretedSplices .~ is
is = do
"fact" ## factSplice
This uses lenses to access the fields of the SpliceConfig neutral element mempty, so I had to add Control.Lens to the dependencies in Site.hs, as well as Data.Monoid to put mempty in scope. I also changed the type signature of the factorial splice to factSplice :: Monad n => I.Splice n, but the function is otherwise unchanged from its form in the Heist tutorial. Then I put a call to addMySplices in the application initializer, right next to addAuthSplices in Site.hs
app :: SnapletInit App App
...
addAuthSplices h auth
addMySplices h
...
which results in factSplice being bound to the tag <fact>. Dropping <fact>8</fact> into one of the default templates renders 40320 on the page, as advertised.
This question from about a year ago contains a superficially similar solution, but does not work with the latest version of Heist; the difference is that some fields were made accessible through lenses instead of directly, which is explained on the Snap project blog in the announcement of Heist 0.14. In particular, hcCompliedSplices has been completely redefined - there's even a friendly warning about it in Types.hs.
If you look at the top level Heist module, you'll see the initHeist function. As the documentation points out, this is the main initialization function. And you are supposed to pass it all of your templates and splices. A look at the type signature tells us these are all bundled together in the HeistConfig data type.
initHeist :: Monad n => HeistConfig n -> EitherT [String] IO (HeistState n)
This gives you back a HeistState, which is what you pass to renderTemplate when you want to render a template. Also, HeistConfig contains a SpliceConfig field for all your splices.
But this is all the low level interface. Heist was designed to have no dependencies on Snap. It is a template library and can work with any web framework. (Or even standalone with no web framework at all for things like generating HTML email.) If you're using Heist with Snap, you'll probably want to use the convenience stuff that we supply which handles the details of calling initHeist, renderTemplate, etc.
For a working example of this, your best bet is to look at the project template that you get when you do "snap init". You can see that code on github here. If you look in Application.hs, you'll see that there's a line including the Heist snaplet in the application data structure. Then, if you look at the bottom of Site.hs, you'll see that there's a call to heistInit. This function is defined by the heist snaplet here. The snaplet takes care of the initialization, state management, on-the-fly template reloading, etc for you.
So, to put this all together...from the Heist API described above, we see that we need to define our splices inside HeistConfig. But our application will interact with all this stuff mostly through the snaplet's API. So if we look in the heist snaplet API for something involving HeistConfig/SpliceConfig, we find two relevant functions:
heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b)
addConfig :: Snaplet (Heist b) -> SpliceConfig (Handler b b) -> Initializer b v ()
These type signatures suggest two ways of defining your splices. You could use heistInit' instead of heistInit and pass your HeistConfig to it up front. Or you could add your splices afterwards by calling addConfig with the resulting Snaplet (Heist b).

How to extract BrowserState from BrowserAction monad?

I'm coding a http client as a learning project with the use of network-http package (http://hackage.haskell.org/package/HTTP-4000.2.2) .
There is a Network.Browser module which defines getBrowserState function.
Probably just a lame beginner question but how can I get BrowserState record from BrowserAction monad if Network.Browser module does not export data constructor or record's lift function ?
import Network.Browser
-- getBrowserState :: BrowserAction t (BrowserState t)
extractBS :: BrowserAction t (BrowserState t) -> BrowserState t
-- ??? implementation ???
In addition what about further handling of BrowserState fields like bsCookies, bsDebug, bsProxy etc. ? (http://hackage.haskell.org/packages/archive/HTTP/4000.2.2/doc/html/src/Network-Browser.html#BrowserState)
What you're trying to do doesn't really make sense. A BrowserAction describes an action, while a BrowserState describes the current state of the browser at some point within an action.
The only way of getting something out of a BrowserAction is to run it with the browse function.
browse :: BrowserAction conn a -> IO a
It's essentially the same as why you can't get a Something out of an IO Something, except here you have the function browse which allows you to "get stuff out of" a browser action by running it.
For example, you can make an action that extracts the current browser state after the original action and run that:
browse (action >> getBrowserState) :: IO (BrowserState conn)
Note the IO in the type here, as running the action may have side effects.
That said, I suspect that what you really want is to make the code that needs the current browser state part of an action.
browse $ do action
state <- getBrowserState
-- do stuff with the state
Note that BrowserAction has a MonadIO instance, so you can still do IO stuff by using liftIO.
browse $ do -- browsing
liftIO $ putStrLn "foo"
-- more browsing
In other words, you shouldn't think of it as getting stuff out of a BrowserAction. You should instead think of how to make the browsing-related code part of a BrowserAction which you then run with browse.

UI input with reactive-banana-wx

How do you get the content of ui elements when using reactive-banana? The event0 returns an event of type Event (), which has unit type instead of the type of the control. event1 takes an event of type Event w (a -> IO ()), but command is of type Event w (IO ()). mapAccumE and mapAccumB takes pure functions as parameters, so get text foo can't be used with them.
Basically, you want to work with functions instead of data. If you're thinking "How do I create a behavior which has the current text in a box", you don't. Instead you write functions that take the current text as a parameter, and pass it in when necessary. Suppose you want to print the contents of a textbox when a button is pressed. Then you would do something like this:
eButton :: NetworkDescription (Event ())
eButton = event0 button command
network = do
pressButton <- eButton
reactimate $ (\() -> get text foo >>= print) <$> pressButton
If you need to get input into a Behavior, you can similarly use a function with type Behavior (String -> a) (or whatever type you need), and then just pass the string in at the point of the reactimate call.
(Author of reactive-banana speaking. Sorry for the late reply, the possibility of questions being asked here didn't even cross my mind. :-) )
I discovered today that I omitted a very crucial feature from the library: getting the content of a UI element as a Behavior. Embarassing! :-D
John describes the current workaround, but the next version of reactive-banana will include the missing feature.
EDIT: I have released reactive-banana version 0.4 which now includes the functionality in form of a function
fromPoll :: IO a -> NetworkDescription (Behavior a)

Resources