如何使用Haskell的C库?

时间:2019-06-09 05:26:30

标签: c haskell interop ffi

我正在尝试使用FFI从Haskell调用C函数,但不断出现此错误:

  

ghc.exe:^^无法加载'getSize',依赖关系未解决。见顶部   上面的条目。

     

主要:ByteCodeLink:找不到标签在交互式链接期间,GHCi   找不到以下符号:getSize这可能是由于您造成的   不要求GHCi加载所需的额外目标文件,档案或DLL   您当前的会话。重新启动GHCi,指定缺少的库   使用-L / path / to / object / dir和-lmissinglibname标志,或者简单地   通过在GHCi命令行上命名相关文件。或者,   此链接失败可能表明GHCi中存在错误。如果您怀疑   后者,请将错误报告发送至:
  glasgow-haskell-bugs@haskell.org

我正在使用我的C库中的stdio.h库:

C库

// lib.h
#include <stdio.h>

double getSize() {
    double size = 0;
    scanf("$f", &size);
    return size;
}

FFI模块

{-# LANGUAGE ForeignFunctionInterface #-}
module Ffi where

import Foreign
import Foreign.C.Types

foreign import ccall "lib.h getSize" c_size :: IO Double

主要

module Main where
import Ffi

main :: IO ()
main = do a <- getLine
          b <- c_size
          print $ "got from C: " ++ show b

运行脚本

gcc -o lib -lib.h
runghc main

PS ?可能是因为我也不得不在其他地方指定依赖项stdio.h吗?

1 个答案:

答案 0 :(得分:3)

好的,这里有几件事要做:

  • 将“ lib.h”重命名为“ lib.c”。这是一个C源文件(包含代码),而不是C头文件。
  • 理想情况下,为getSize的原型添加一个单独的“ lib.h”头文件。
  • 修复“ lib.c”中的错误。您希望用“%lf”代替“ $ f”来读一遍。
  • 使用ghc编译程序,而不是使用runghc运行程序。单个ghc命令可以编译并链接Haskell模块和C代码。

换句话说,您的文件应如下所示:

// lib.c
#include "lib.h"
#include <stdio.h>
double getSize() {
    double size = 0;
    scanf("%lf", &size);
    return size;
}
// lib.h
double getSize(void);
-- Ffi.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Ffi where
import Foreign
import Foreign.C.Types
foreign import ccall "lib.h getSize" c_size :: IO Double
-- Main.hs
module Main where
import Ffi
main :: IO ()
main = do a <- getLine
          b <- c_size
          print $ "got from C: " ++ show b

,您应该使用以下命令进行编译:

$ ghc Main.hs lib.c
[1 of 2] Compiling Ffi              ( Ffi.hs, Ffi.o )
[2 of 2] Compiling Main             ( Main.hs, Main.o )
Linking Main ...

然后您可以运行它,为Haskell getLine提供一行,为C scanf提供第二行,它应该可以正常工作:

$ ./Main
hello world!!   -- line for Haskell
135.0           -- line for C
"got from C: 135.0"