Search code examples
chaskellffic2hs

linker error in C2HS generated C binding


I build and run the following minimal example (no external dependencies) with C->Haskell Compiler, version 0.25.2 Snowboundest, 31 Oct 2014 build platform is "x86_64-darwin" <1, True, True, 1> ; build command:

c2hs Structs.chs
ghci Structs.hs

but the linker complains with a

During interactive linking, GHCi couldn't find the following symbol: get_foo

Q : Why is this and how can I fix it? Thx in advance

A : tl;dr : I wasn't compiling the .c into .o object code, DUH!

Code follows:

Structs.chs

module Main where

import Foreign
import Foreign.C

#include "Structs.h"

{#pointer *foo as Foo#}

{#fun get_foo {`Int'} -> `Foo' return* #}

main :: IO ()
main = do
  foo <- get_foo 3
  a1 <- {#get struct foo->a#} foo
  print a1

Structs.h

struct foo {
  int a;
};

struct foo *get_foo(int n);

Structs.c

#include "Structs.h"

struct foo f;

struct foo *get_foo(int n)
{
  f.a = n;
  return &f;
}

Structs.hs

-- -- C2HS generated Hs file, edited for clarity
module Main where

import Foreign
import Foreign.C

type Foo = Ptr ()

get_foo :: Int -> IO Foo
get_foo p =
  get_foo'_ (fromIntegral p)

main :: IO ()
main = do
  foo <- get_foo 3
  a1 <- (\ptr -> peekByteOff ptr 0 :: IO CInt) foo
  print a1

foreign import ccall safe "Structs.chs.h get_foo"
  get_foo'_ :: CInt -> IO Foo

EDIT : ghc --make Structs.hs gives the same linker error:

$ ghc --make Structs.hs
Linking Structs1a ...
Undefined symbols for architecture x86_64:
"_get_foo", referenced from:
    _c2MX_info in Structs.o
    _c2Or_info in Structs.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Solution

  • The get_foo C function is defined in Structs.c, so you need to make that available to GHC. This ought to work:

    gcc -o Structs_c.o -c Structs.c
    ghc --make Structs.hs Structs_c.o
    

    For GHCi, I think you can then just say ghci Structs.hs Structs_c.o. But you definitely need the C object file!