Как использовать библиотеку C от Haskell? - PullRequest
0 голосов
/ 09 июня 2019

Я пытаюсь вызвать функцию C из Haskell, используя FFI, и продолжаю получать эту ошибку:

ghc.exe: ^^ Не удалось загрузить 'getSize', зависимость не устранена.См. Верхнюю запись выше.

main: ByteCodeLink: не удается найти метку Во время интерактивной ссылки GHCi не смог найти следующий символ: getSize Это может быть связано с тем, что вы не просили GHCi загрузить дополнительные объектные файлы, архивыили DLL, необходимые для вашей текущей сессии.Перезапустите GHCi, указав отсутствующую библиотеку, используя флаги -L / path / to / object / dir и -lmissinglibname или просто указав соответствующие файлы в командной строке GHCi.Кроме того, эта ошибка ссылки может указывать на ошибку в GHCi.Если вы подозреваете последнее, отправьте отчет об ошибке по адресу:
glasgow-haskell-bugs@haskell.org

Я использую библиотеку stdio.h в моей библиотеке C:

Библиотека 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

Main

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 Ответ

3 голосов
/ 09 июня 2019

Хорошо, здесь можно сделать несколько вещей:

  • Переименуйте "lib.h" в "lib.c". Это исходный файл C (содержащий код), а не заголовочный файл C.
  • В идеале, добавить отдельный заголовочный файл "lib.h" с прототипом для getSize.
  • Исправлена ​​ошибка в "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"
...