使用.NET GUI创建Haskell应用程序

时间:2012-03-19 08:16:51

标签: haskell cabal

我想用.NET gui创建一个Haskell应用程序。我想使用cabal作为我的构建工具来利用它的包管理等。我认为Haskell部分应该是调用.NET代码的可执行文件:

  1. 这样可以避免手动初始化Haskell RTC,如下所述:http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/win32-dlls.html

  2. cabal无法轻松生成Windows dll:http://www.haskell.org/haskellwiki/Cabal/Developer-FAQ#Building_DLLs__with_Cabal

  3. 我发现创建一个使用hs-dotnet调用.NET的Haskell可执行文件相当容易,但是我还需要我的GUI代码才能回调到Haskell。我希望使用Haskell的“外部导出”命令来实现这一点,然后通过.NET native interop调用这个导出的函数。但是,“外部导出”功能似乎并没有在可执行文件中创建一个入口点,当我对生成的可执行文件执行dumpbin /EXPORTS时,我看不到入口点。我不确定这是否是因为GHC只在通过-shared开关创建dll时创建了入口点,或者cabal是否添加了一个禁止创建入口点的标志。

    所以我想问题是如何强制GHC在我的Windows可执行文件中创建入口点?或者我会更好地使用.NET可执行文件,通过必要的步骤创建一个带有cabal的Haskell dll并手动初始化Haskell RTC?

1 个答案:

答案 0 :(得分:4)

我通常通过将回调作为函数指针传递来解决这个问题。例如,我有一个应用程序,按下按钮需要回调Haskell(我使用的是Cocoa,但名称非常相似)。

首先,我将NSButton对象子类化,并为我的新ButtonC类提供类型为void(*onClickCallback)()的私有成员。我还声明了一个函数void setClickCallback(ButtonC *button, void(*callback)());实现你的子类,这样无论何时单击该按钮,都会调用函数指针。在.Net中,可能有一种聪明的方式与代表这样做(自从我使用.Net以来已经有一段时间了。)

接下来,我的Haskell绑定看起来像这样(省略了一些代码):

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 = ...

现在,IO ()类型的Haskell数据可以包装在FunPtr中,并通过buttonSetCallback传递到GUI中。只要按下按钮,就会执行IO ()操作。

createButton :: IO ButtonPtr
createButton = do
    btn <- buttonNew
    let buttonClicked = print "The button was clicked!"
    btnCallback <- makeClickCallback buttonClicked
    buttonSetCallback btn btnCallback
    return btn

要注意FunPtr的一件事是它们不是垃圾收集的。您需要在完成后手动取消分配它们,否则您将发生内存泄漏。一个好的做法是永远不要共享FunPtr,也永远不要在Haskell方面保留对它们的引用。这样,您的对象可以释放FunPtr作为其清理的一部分。这需要对Haskell(一个freeFunPtr函数)进行另一次回调,该回调应该在所有对象之间共享,并且只有在可执行文件终止时才会释放。