gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 12:35:34 27 4
gpt4 key购买 nike

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

  • 这避免了必须手动初始化 Haskell RTC,如下所述:http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/win32-dlls.html
  • cabal 无法轻松生成 Windows dll:http://www.haskell.org/haskellwiki/Cabal/Developer-FAQ#Building_DLLs__with_Cabal

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

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

    最佳答案

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

    首先,我将一个 NSButton 对象子类化,并给我的新 ButtonC 类一个类型为 void(*onClickCallback)() 的私有(private)成员。 .我还声明了一个函数 void setClickCallback(ButtonC *button, void(*callback)());实现您的子类,以便在单击按钮时调用函数指针。在 .Net 中,可能有一种巧妙的方式来处理委托(delegate)(我使用 .Net 已经有一段时间了)。

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

    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 ()执行 Action 。
    createButton :: IO ButtonPtr
    createButton = do
    btn <- buttonNew
    let buttonClicked = print "The button was clicked!"
    btnCallback <- makeClickCallback buttonClicked
    buttonSetCallback btn btnCallback
    return btn

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

    关于haskell - 使用 .NET GUI 创建 Haskell 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9766874/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com