简体   繁体   中英

Using a haskell function from C++: Undefined reference error

I want to call haskell functions out of C++ and did use the tutorial at http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/ffi-ghc.html

So I have a haskell file Foo.hs:

module Foo where

foreign export ccall foo :: Int -> IO Int

foo :: Int -> IO Int
foo n = return (length (f n))

f :: Int -> [Int]
f 0 = []
f n = n:(f (n-1))

and called

ghc Foo.hs

which created a Foo_stub.h:

#include "HsFFI.h"
#ifdef __cplusplus
extern "C" {
#endif
extern HsInt foo(HsInt a1);
#ifdef __cplusplus
}
#endif

a Foo_stub.c:

#define IN_STG_CODE 0
#include "Rts.h"
#include "Stg.h"
#ifdef __cplusplus
extern "C" {
#endif

extern StgClosure Foo_zdffoozualy_closure;
HsInt foo(HsInt a1)
{
Capability *cap;
HaskellObj ret;
HsInt cret;
cap = rts_lock();
cap=rts_evalIO(cap,rts_apply(cap,(HaskellObj)runIO_closure,rts_apply(cap, Foo_zdffoozualy_closure,rts_mkInt(cap,a1))) ,&ret);
rts_checkSchedStatus("foo",cap);
cret=rts_getInt(ret);
rts_unlock(cap);
return cret;
}
static void stginit_export_Foo_zdffoozualy() __attribute__((constructor));
static void stginit_export_Foo_zdffoozualy()
{getStablePtr((StgPtr) &Foo_zdffoozualy_closure);}
#ifdef __cplusplus
}
#endif

It also created a Foo_stub.o file.

I now created a main.cpp file:

#include "Foo_stub.h"
int main()
{
  foo(3);
}

and tried to compile it.

Using g++ failed:

$ g++ -I/usr/lib/ghc-7.0.3/include/ main.cpp Foo_stub.o
Foo_stub.o: In function `foo':
Foo_stub.c:(.text+0xa): undefined reference to `rts_lock'
Foo_stub.c:(.text+0x18): undefined reference to `rts_mkInt'
Foo_stub.c:(.text+0x20): undefined reference to `Foo_zdffoozualy_closure'
Foo_stub.c:(.text+0x28): undefined reference to `rts_apply'
Foo_stub.c:(.text+0x30): undefined reference to `base_GHCziTopHandler_runIO_closure'
Foo_stub.c:(.text+0x38): undefined reference to `rts_apply'
Foo_stub.c:(.text+0x48): undefined reference to `rts_evalIO'
Foo_stub.c:(.text+0x58): undefined reference to `rts_checkSchedStatus'
Foo_stub.c:(.text+0x62): undefined reference to `rts_getInt'
Foo_stub.c:(.text+0x6d): undefined reference to `rts_unlock'
Foo_stub.o: In function `stginit_export_Foo_zdffoozualy':
Foo_stub.c:(.text+0x80): undefined reference to `Foo_zdffoozualy_closure'
Foo_stub.c:(.text+0x85): undefined reference to `getStablePtr'
collect2: ld returned status 1

so I tried ghc --make. But this also failed:

$ ghc --make main.cpp Foo_stub.o
cc1plus: Warning: Option »-Wimplicit« is valid for C/ObjC, but not for C++ [activated by default]
Foo_stub.o: In function `foo':
Foo_stub.c:(.text+0x20): undefined reference to `Foo_zdffoozualy_closure'
Foo_stub.o: In function `stginit_export_Foo_zdffoozualy':
Foo_stub.c:(.text+0x80): undefined reference to `Foo_zdffoozualy_closure'
collect2: ld returned status 1

How can I compile it?

Try this:

$ ghc --make -no-hs-main main.cpp Foo.hs

I believe the problem is that GHC thinks the stub object file you're passing in is just another object to be linked normally, but you're not passing the Foo.o file itself, so the stub code has nothing to link to! Passing in the source file directly should solve it. (This is just conjecture based on the documentation and the error you're seeing, I haven't tested it.)

I think you could do separate compilation like this:

$ ghc --make Foo.hs
$ ghc --make -no-hs-main main.cpp Foo.o

but I'm not sure. You might also want to look into building your Haskell code into a shared library , and then linking it to your main program normally with g++ .

-no-hs-main is required when your program's entry point isn't the Haskell value Main.main , as described in the documentation you linked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM