Использование функции haskell из C ++: неопределенная ошибка ссылки - PullRequest
2 голосов
/ 28 декабря 2011

Я хочу вызывать функции haskell из C ++ и использовал учебник на http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/ffi-ghc.html

Итак, у меня есть файл haskell 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))

и называется

ghc Foo.hs

, который создал 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

Он также создал файл Foo_stub.o.

Я сейчас создал файл main.cpp:

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

и попытался скомпилировать.

Не удалось использовать g ++:

$ 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

поэтому я попробовал ghc --make. Но и это не удалось:

$ 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

Как мне его скомпилировать?

1 Ответ

7 голосов
/ 28 декабря 2011

Попробуйте это:

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

Я полагаю, что проблема в том, что GHC считает, что объектный файл-заглушка, который вы передаете, является просто другим объектом, который обычно связывается, но вы не передаете сам файл Foo.o, поэтому код-заглушка не имеет ничего для связи к! Передача в исходном файле напрямую должна решить это. (Это всего лишь предположение, основанное на документации и появившейся ошибке, я ее не проверял.)

Я думаю, вы могли бы сделать отдельную компиляцию следующим образом:

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

но я не уверен. Вы также можете захотеть встроить свой код на Haskell в общую библиотеку , а затем связать его с основной программой, как правило, с помощью g++.

-no-hs-main требуется, если точка входа вашей программы не является значением Haskell Main.main, как описано в документации, которую вы связали.

...