Haskell FFI 本地 c 标头

问题描述 投票:0回答:1

我想用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)

我该如何解决这个问题?

haskell
1个回答
5
投票

如果它是一个仅包含头文件的库,则需要一个 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
来生成最终的构建结果。 本教程更详细地介绍了该过程。但对于这个简单的用例,您可以仅使用
c-sources
部分
在 Cabal 中执行此操作:

c-sources: nuklear.c

您可能还需要指定

includes
include-dirs
,例如:

includes: nuklear.h
© www.soinside.com 2019 - 2024. All rights reserved.