Haskell FFI local c header - haskell

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

Related

Haskell FFI: stack run is ok, but GHCi does not link properly

I am trying to learn how to structure a Haskell project/workflow that uses FFI.
I am using stack, but I find myself unable to use GHCi when it comes to the imported foreign functions.
Here is a simplified version of the problem. Let's say that I have the following two files in $PROJECT_ROOT/cbits:
hello.h
#ifndef HELLO_H
#define HELLO_H
extern "C"
{
int foo();
}
#endif /* HELLO_H */
hello.cpp
#include "hello.h"
#include <iostream>
int foo()
{
std::cout << "extremely dangerous side effect" << std::endl;
return 42;
}
My Main.hs file:
module Main where
import Foreign.C
foreign import ccall unsafe "foo" foo :: IO CInt
-- this does side effects and prints '42'
main = foo >>= print
The relevant (C++ specific) section of my package.yaml is:
include-dirs:
- cbits
cxx-sources:
- cbits/*.cpp
cxx-options:
- -std=c++17
extra-libraries:
- stdc++
I am using the souffle-haskell's package.yaml as a reference.
Compiling and running with stack run is ok and I get the expected output:
extremely dangerous side effect
42
But, in the GHCi session (run with stack ghci), calling main gives:
ghc: ^^ Could not load 'foo', dependency unresolved. See top entry above.
GHC.ByteCode.Linker: can't find label
During interactive linking, GHCi couldn't find the following symbol:
foo
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. 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.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please report this as a GHC bug:
https://www.haskell.org/ghc/reportabug
The problem is not present if I compile hello.cpp beforehand:
g++ -c cbits/hello.cpp -o cbits/hello.o
And then run stack ghci --ghci-options cbits/hello.o, as suggested by the GHCi error message.
Question is: do I really need to maintain a separate *.o file specifically for GHCi? Searching online I have found discussions addressing only the GHCi part or the stack/cabal part, but not both. The only useful answer that I have found is this one from 2013, which reaffirms the "solution" given by GHCi and does not mention stack or cabal.
Question is: do I really need to maintain a separate *.o file specifically for GHCi?
Answer is: no.
After several tries, the only thing that I had to change was the name of an option:
- cxx-sources:
+ c-sources:
This left the behaviour of stack run unchanged, and allowed GHCi to link properly to the compiled code.

When linking a shared library on linux, are all modules included?

I'm porting a system of apps from AIX to linux, and all of those apps include a single shared library. I've got the shared library building on as a linux .so now - and I see at least one post here that describes how to specify what's exported from a shared library (as AIX does via a .exp file).
Just one silly question, though. On AIX, if a module in a shared library is not referenced by anything in the app that's linking to it, it is ignored by the linker. That doesn't seem to be the case on linux - but I want to make sure.
While testing my linux shared library, I left out one module with dependencies I wasn't ready to deal with yet (or more accurately, I provided a substitute module with dummy functions for all the entry points to that module, thinking that would allow it to link). So far, so good. But when I attempted to link that shared library into a trivial test app, the linker reported unresolved symbols for stuff referenced by another shared library module that is itself only referenced from within the module I replaced with dummies. I.e., I would have expeceted that module to simply be ignored...
In other words, this module is being considered by the linker as part of the final application even though nothing in the app references it. I tried the same experiment on AIX (replacing the same module with dummies and attempting to link a trivial app there). No complaints.
So, The AIX linker only attempts to resolve shared library module dependencies if those modules themselves are explicitly called in from the application. But the linux linker attempts to resolve dependencies for all shared library modules whether they're called in from the application or not.
Is this true? And if so, is there any way to override that behavior? Ultimately, when I port everything, all of the dependencies will resolve. But for now, it's hard to leave something out - even if it's not referenced...
Here's a minimal case:
main.c contains function main(), which calls function one().
one.c contains function one(), which does nothing.
two.c contains function two(), which calls function three().
There is no function three(), but libshared.so is built from
modules one.c and two.c. Program main is built from main.c and
links in libshared.so.
The linker needs to resolve function one(), which is in the shared
library. But that's all main.c requires. Still, function two() in
the library references function three(), which doesn't exist.
The linker will complain about the undefined symbol 'three', even
though program main doesn't need it.
On AIX the linker will not complain and everything will work.
main.c:
#include <stdio.h>
int one();
int main()
{
one();
}
one.c:
#include <stdio.h>
int one()
{
return 1;
}
two.c:
#include <stdio.h>
int three();
int two()
{
return three();
}
build libshared.so with modules one.c and two.c:
gcc -fPIC -shared one.c two.c -o libshared.so
Attempt to build main from main.c and libshared.so:
gcc main.c -o main -L. -lshared
./libshared.so: undefined reference to `three'
collect2: error: ld returned 1 exit status
The linker reports an undefined reference to 'three',
which is referenced from two() - but main() doesn't ever call two().
The actual answer: shared libraries are in fact shared objects: they are treated as a single object, not as a *.a library.
This shows that Linux (meaning: glibc/gcc/gold/ld) and AIX have different concepts regarding shared objects.
In Linux, when you link an executable, ld/gold checks the dependencies of the used shared objects as well -- Aix linker doesn't: it assumes that the shared objects are to be used as they are, their dependencies aren't part of the current linking. (At least this is the default behaviour.)
Here is a summary of my tests:
+----------------+--------------------+-------------------------------+
| | AIX | linux |
+----------------+--------------------+-------------------------------+
| libshared.so | only with option | yes |
| can be created | -Wl,-berok | |
+----------------+--------------------+-------------------------------+
| main | yes | only with option |
| can be created | | -Wl,--allow-shlib-undefined |
+----------------+--------------------+-------------------------------+
Note: My random thoughts regarding AIX and linking: http://lzsiga.users.sourceforge.net/aix-linking.html
By default the GNU binutils linker, ld on
Linux requires a symbol ref to be defined by some input file (i.e. object file or
shared library) in the linkage if ref is referenced by the definition of any
symbol def in any input file that the linkage needs. It doesn't matter whether def is referenced in turn.
Your program linkage needs libshared.so. libshared.so defines two, which refers to three,
so three must be defined.
You can countermand this default behaviour to tolerate undefined references in shared libraries
(but not in object files) as follows:
$ gcc main.c -o main -L. -lshared -Wl,--allow-shlib-undefined
--allow-shlib-undefined is documented in the ld manual
The notion of module in your language corresponds to translation unit at the
compilation level and object file at the linkage level. It might be helpful to
appreciate that an object file input to the linkage of a ELF program or shared library
has no distinct existence in the program or shared library. It is cut into
pieces and scattered around. So there is no sense in which it would be possible
for a linkage:
$ gcc main.c -o main -L. -lshared ...
to ignore the unreferenced module two.(c|o) within
libshared.so. There is no such thing. If that linkage did not need any
definition provided by libshared.so then it would ignore the shared library
altogether1. If it needs the shared library, then by default its references
must be resolved.
[1] That is, on Debian-clan systems where gcc is built to invoke ld with the --as-needed option
by default. On Redhat-clan systems GCC by default links shared libraries if they are input, needed or not.

How do I configure Cabal to understand a C FFI?

I am trying to create a Haskell library which uses a C FFI. I have 4 files:
MyLibrary.hs
c_dependency.h
c_dependency.c
c_dependency.o
test.hs
All on the same directory. test.hs loads MyLibrary and tests it:
-- test.hs
import qualified MyLibrary as Lib
main = Lib.test
I want to be able to compile test.hs as usual, without linking to c_dependency.o. That is, I want ghc test.hs; ./test to work. How can I init/configure cabal so it builds my library properly, taking care of linking c_dependency.o ?
A series of blog posts on Cabal, the FFI, and c2hs has what you're looking for in the second article, the "Compiling the library with Cabal" section.

cabal FFI dependency

I am making a small Haskell game in Windows, where I would like to respond each time the user presses a key. Because getChar behaves strangely on Windows, I use FFI to get access to getch in conio.h, as described here. The relevant code is:
foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt
This works fine, when I run it in ghci, or compile it with ghc. I also want to try making a cabal package out of it, so extending from this question, I include the following in my cabal file:
...
executable noughts
Includes: conio.h
Extra-libraries conio
...
But when I run cabal configure, it tells me:
cabal: Missing dependency on a foreign library:
* Missing C library: conio
It makes sense, because in my haskell platform directory, under ...\Haskell Platform\2012.4.0.0\mingw there is a conio.h file under the include directory, but no other conio file to provide the object code.
Am I doing this the right way, and if so, how can I find out which library to include in my cabal file?
First off, there is not always a one-to-one mapping between C header files and libraries. In this case, the functions declared in conio.h can be found in various runtime libraries, such as crtdll (deprecated) or msvcrt (preferred, I guess).
With the Haskell Platform on Windows, Cabal will look for these libraries in .\mingw\lib (under your Haskell Platform directory): if you ask for msvcrt, it will look for .\mingw\lib\libmsvcrt.a. This specific library should already be shipped with your Haskell Platform. (If you want to point to other directories with lib*.a files, you can use Cabal's --extra-lib-dirs option.)
A tiny example of this would be as follows; this is Main.hs:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
foreign import ccall unsafe "conio.h _putch" c_putch :: CInt -> IO ()
main :: IO ()
main = do
c_putch . toEnum . fromEnum $ '!'
c_putch . toEnum . fromEnum $ '\n'
And this would be something-awesome.cabal:
name: something-awesome
version: 0.1.0.0
build-type: Simple
cabal-version: >=1.8
executable yay
main-is: Main.hs
build-depends: base ==4.5.*
includes: conio.h
extra-libraries: msvcrt
This should work fine:
c:\tmp\something-awesome> dir /B
Main.hs
something-awesome.cabal
c:\tmp\something-awesome> cabal configure
Resolving dependencies...
Configuring something-awesome-0.1.0.0...
c:\tmp\something-awesome> cabal build
Building something-awesome-0.1.0.0...
Preprocessing executable 'yay' for something-awesome-0.1.0.0...
[1 of 1] Compiling Main ( Main.hs, dist\build\yay\yay-tmp\Main.o )
Linking dist\build\yay\yay.exe ...
c:\tmp\something-awesome> dist\build\yay\yay.exe
!

Haskell: How do I get the values of #define-d constants?

In a Haskell program, what's the best way to use constants defined in C headers?
For this task, hsc2hs is your friend.
For a simple example, let's get the value of INT_MAX from limits.h.
$ cat >IntMax.hsc
module Main where
#include <limits.h>
c_INT_MAX = #const INT_MAX
main = print c_INT_MAX
With hsc2hs, we can #include headers and use the values of constants with the #const directive.
Instead of building by hand, use Cabal:
$ cat >intmax.cabal
Name: intmax
Version: 0.0
Cabal-Version: >=1.2
Build-Type: Simple
Executable intmax
Main-Is: IntMax.hs
Build-Depends: base
Notice that even though the name of the main program is IntMax.hsc, the Main-Is line points to IntMax.hs. When Cabal looks for IntMax.hs but finds IntMax.hsc, it automatically feeds the latter through hsc2hs as part of the build.
$ cabal configure
Resolving dependencies...
Configuring intmax-0.0...
$ cabal build
Prerocessing executables for intmax-0.0...
Building intmax-0.0...
[1 of 1] Compiling Main ( dist\build\intmax\intmax-tmp\IntMax.hs, dist\build\intmax\intmax-tmp\Main.o )
Linking dist\build\intmax\intmax.exe ...
$ ./dist/build/intmax/intmax
2147483647
Note that you'll want to break up lines with multiple constants. Say you're assembling a bitfield to pass to FormatMessage. You'll want to write it as
flags = #const FORMAT_MESSAGE_FROM_SYSTEM
.|.
#const FORMAT_MESSAGE_IGNORE_INSERTS
Putting them all on one line will result in syntax errors.
GHC is moving away from -fvia-c and towards -fasm wherever possible.
One side effect is that your program may be compiled without using any C headers at all, even in -fvia-c mode, in order to ensure that the compilation results are functionally identical to GHC in -fasm mode.
Thus it is necessary to use hsc2hs, c2hs, or other preprocessors run before GHC compiles sources.
c2hs natively supports enum constants... it's been a while, but I think something like this is right.
#c
enum Foo = { Bar, Baz };
void something(enum Foo foo) {}
#endc
{#enum Foo#}
somethingBar = {#call pure something#} (cFromEnum Bar)
#define'd constants are a tick trickier. I've always just copied them inline, or used additional C to transform then into enums or const variables.

Resources