简体   繁体   English

如何使用Haskell的C库?

[英]How to use C library from Haskell?

I am trying to call a C function from Haskell using the FFI and I keep getting this error : 我试图使用FFI从Haskell调用C函数,但不断出现此错误:

ghc.exe: ^^ Could not load 'getSize', dependency unresolved. ghc.exe:^^无法加载'getSize',依赖关系未解决。 See top entry above. 请参阅上面的顶部条目。

main: ByteCodeLink: can't find label During interactive linking, GHCi couldn't find the following symbol: getSize This may be due to you not asking GHCi to load extra object files, archives or DLLs needed by your current session. main:ByteCodeLink:找不到标签在交互式链接期间,GHCi找不到以下符号:getSize这可能是由于您没有要求GHCi加载当前会话所需的额外目标文件,档案或DLL。 Restart GHCi, specifying the missing library using the -L/path/to/object/dir and -lmissinglibname flags, or simply by naming the relevant files on the GHCi command line. 重新启动GHCi,使用-L / path / to / object / dir和-lmissinglibname标志,或者仅通过在GHCi命令行上命名相关文件,指定缺少的库。 Alternatively, this link failure might indicate a bug in GHCi. 或者,此链接失败可能表示GHCi中存在错误。 If you suspect the latter, please send a bug report to: 如果您怀疑是后者,请将错误报告发送至:
glasgow-haskell-bugs@haskell.org glasgow-haskell-bugs@haskell.org

I am using the stdio.h library in my C library: 我在C库中使用stdio.h库:

C library C库

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

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

FFI module FFI模块

{-# LANGUAGE ForeignFunctionInterface #-}
module Ffi where

import Foreign
import Foreign.C.Types

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

Main 主要

module Main where
import Ffi

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

Running script 运行脚本

gcc -o lib -lib.h
runghc main

PS Could this be because I somehow have to specify the dependency stdio.h somewhere else too? PS这可能是因为我也必须在其他地方指定依赖项stdio.h吗?

Okay, there are several things to do here: 好的,这里有几件事要做:

  • Rename "lib.h" to "lib.c". 将“ lib.h”重命名为“ lib.c”。 It's a C source file (containing code), not a C header file. 这是一个C源文件(包含代码),而不是C头文件。
  • Ideally, add a separate "lib.h" header file with the prototype for getSize . 理想情况下,为getSize的原型添加一个单独的“ lib.h”头文件。
  • Fix the bug in "lib.c". 修复“ lib.c”中的错误。 You want "%lf" in place of "$f" to read in a double. 您希望用“%lf”代替“ $ f”来读取双精度字。
  • Compile the program with ghc instead of running it with runghc . 使用ghc编译程序,而不是使用runghc运行程序。 A single ghc command can compile and link both Haskell modules and C code. 单个ghc命令可以编译和链接Haskell模块和C代码。

In other words, your files should look like: 换句话说,您的文件应如下所示:

// 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

and you should compile it with: 您应该使用以下命令进行编译:

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

Then you can run it, supply a line for the Haskell getLine and a second line for the C scanf , and it should work fine: 然后您可以运行它,为Haskell getLine提供一行,为C scanf提供第二行,它应该可以正常工作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM