【问题标题】:Haskell FFI: Successful compile and link, app crash with BEX64Haskell FFI:成功编译和链接,BEX64 应用程序崩溃
【发布时间】:2015-03-26 18:54:26
【问题描述】:

我正在学习如何使用 FFI,并从一个非常简单的示例开始,从 Haskell 调用 C 函数。

这一切都在 Windows 7、64 位、Visual Studio Community 2013 下。

C 看起来像这样:

_declspec(dllexport) int line(int m, int b, int x) {
    return m * x + b;
}

我已将 VS 编译器设置为生成 64 位 DLL,它会生成一个名为 simpleclib.dll 的 DLL(也有匹配的 .lib 文件)

匹配的 Haskell 如下所示:

module Main (main) where

foreign import ccall "line" cline :: Int -> Int -> Int -> Int

main = do
    putStr "hello,world\n"
    putStr (show y)

y = cline 2 5 10

GHC 是在上个月 7.8.3 内下载的。

ghc 的命令行是这样的:

c:\> ghc foreign -L. -lsimpleclib

这运行成功,按预期生成 .EXE。

运行程序会在 BEX64 上产生应用崩溃:

问题事件名称:BEX64 应用程序名称:foreign.exe 应用程序版本:0.0.0.0 申请时间戳:551048a6 故障模块名称:StackHash_0981 故障模块版本:0.0.0.0 故障模块时间戳:00000000 异常偏移量:0000000000000000 异常代码:c0000005 异常数据:0000000000000008 操作系统版本:6.1.7601.2.1.0.256.4 区域设置 ID:1033 附加信息 1:0981 附加信息2:09817cdf87ca03322f39545f3e74c62d 附加信息 3:31c0 附加信息4:31c0a543af0be952ecd86b6ee71cc83a

我也尝试过使用 Data.Int.Int64 的参数定义。结果一样。

有人有什么想法吗?

谢谢, 顺手

【问题讨论】:

  • 使用CInt,而不是Int。不确定这是否是唯一的问题,从未尝试链接到 Windows dll。
  • 好主意。刚试了一下。结果相同。到目前为止,我已经尝试过 Int、CInt、Int32 和 Int64,认为这可能是某种堆栈未对齐的事情。都给出相同的结果。稍微深入了解调试器会发现根本问题是(当然)0x0000000000000000(64 位 0)处的访问冲突。奇怪,因为我看不到可以进行任何明显的调整。

标签: c haskell ffi


【解决方案1】:

我找不到告诉 VS 创建 64 位 dll 的旋钮,所以我尝试了 gcc(在 Win 7 上,64 位)。我不得不以两种方式更改您的 c 程序的第一行,添加 __cdecl,并使 _cdecl 有 2 个下划线: __declspec(dllexport) int __cdecl line(int m, int b, int x) {

C:\...\>foreign
hello,world
25

`

【讨论】:

  • 越来越有趣了。我将不得不阅读 gcc 上的开关并尝试一下,但我毫不怀疑它会起作用。因此,在 VS 中,要构建 64 位 dll,您需要进入配置管理器并添加 x64 作为配置。因此,当我将第二个下划线添加到“__declspec”时,所有内容都已编译、链接和运行而没有崩溃,除了没有写入输出。太奇怪了!如果我注释掉写出 y 的行,它就会运行,我会收到 hello,world 消息。有了线路,什么都没有。这个家用机器(仍然是 64 位 Win 7)原始示例正在工作中。
  • 更新:在工作中,它使用 gcc 构建并运行良好。我不知道 Visual Studio 编译器/链接器是怎么回事。
【解决方案2】:

VS 生成的 64 位导入库实际上是 binutils 中的一个错误(.lib 附带 .dll)。请参阅此处的讨论:https://ghc.haskell.org/trac/ghc/ticket/10885#comment:6

可以通过将 GHC 发行版中的 binutils 替换为 MSys2 中的 binutils 来解决该错误。或者,链接器通常能够直接链接.dll 文件,而不需要.lib 文件。这对我来说适用于小例子,但更大的例子可能会失败——我不建议采用这种方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-23
    • 2018-03-11
    • 2012-03-11
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    相关资源
    最近更新 更多