I want to call a C single header library with FFI.
Here's the 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)
In the same directory, I have the nuklear.h
When I do stack ghc Nuk.hs, I get
[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)
How should I solve this?
If it’s a header-only library, you need a C compiler to produce an object file for it so that your Haskell program can link to the definitions. According to the documentation for Nuklear, you can create a stub C file:
// nuklear.c
#define NK_IMPLEMENTATION
#include "nuklear.h"
As part of your build, compile this (e.g. with gcc -c nuklear.c -o nuklear.o) to produce an object file nuklear.o, use ar (e.g. ar -csr libnuklear.a nuklear.o) to create a static library libnuklear.a, then supposing this archive is in libs, you would add:
extra-lib-dirs: libs
extra-libraries: nuklear
To the executable section in your Cabal file. (Or the corresponding section in package.yml for hpack.)
To coordinate this, you might have a Makefile that builds this library and also invokes stack/cabal/ghc to produce the final build result. This tutorial covers the process in a little more explicit detail. But for this simple use case, you may be able to just use the c-sources section to do this from within Cabal:
c-sources: nuklear.c
You may also need to specify includes and include-dirs, e.g.:
includes: nuklear.h
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With