我想用FFI调用C单头库。

这是Nuk.hs

{-# LANGUAGE CPP, ForeignFunctionInterface #-}
module Main where

import Foreign
import Foreign.C.Types

foreign import ccall unsafe "nuklear.h nk_sin"
 c_nk_sin:: IO CFloat

main = print $ c_nk_sin (5)

在同一目录中,我有nuklear.h
当我执行stack ghc Nuk.hs时,我得到
[1 of 1] Compiling Main             ( Nuk.hs, Nuk.o )
Linking Nuk ...
Nuk.o:r1Rq_info: error: undefined reference to 'nk_sin'
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)

我该如何解决?

最佳答案

如果它是仅标头的库,则需要C编译器为其生成目标文件,以便Haskell程序可以链接到定义。根据Nuklear的文档,您可以创建一个存根C文件:

// nuklear.c
#define NK_IMPLEMENTATION
#include "nuklear.h"

作为构建的一部分,将其编译(例如,使用gcc -c nuklear.c -o nuklear.o)以生成目标文件nuklear.o,使用ar(例如ar -csr libnuklear.a nuklear.o)创建一个静态库libnuklear.a,然后假设此归档文件位于libs中,您将添加:
extra-lib-dirs: libs
extra-libraries: nuklear

转到Cabal文件中的executable部分。 (或hpack的package.yml中的相应部分。)

为了对此进行协调,您可能需要一个Makefile来构建该库,并调用stack / cabal / ghc生成最终的构建结果。 This tutorial更详细地介绍了该过程。但是对于这个简单的用例,您也许可以在Cabal内部使用 c-sources section来做到这一点:
c-sources: nuklear.c

您可能还需要指定includesinclude-dirs,例如:
includes: nuklear.h

关于haskell - Haskell FFI本地C header ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53146472/

10-10 07:11