#haskell #ffi #cross-language
#haskell #ffi #кросс-язык
Вопрос:
Я создал статическую библиотеку:
// foo.h
extern "C" {
int foo (const char* arg0, int arg1);
}
// foo.cpp
#include "foo.h"
// implementation of foo
Этот блок кода был скомпилирован foo.o
и упакован, в libfoo.a
который был установлен в lib
каталог MinGW (я на Windows, использую набор инструментов GCC).
Что я хочу сделать, так это обернуть эту функцию в код Haksell, поэтому типичная привязка FFI выглядит следующим образом:
-- Foo.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Foo where
foreign import ccall "foo"
c_foo :: CString -> CInt -> IO (CInt)
extra-libraries
также было добавлено в .cabal
файл:
...
extra-libraries: foo, stdc
Но GHC компилирует неопределенную ссылку на foo
:
.dist-scionbuildpathtoFoo.o:fake:(.text 0x514): undefined reference to `foo'
После nm
того, как библиотека выяснила, какая функция foo
действительно существует в библиотеке (с некоторыми украшениями в названии), я застрял здесь…
[РЕДАКТИРОВАТЬ]
Я также попытался собрать пакет haskell с помощью cabal:
cabal configure
cabal build
Результат показывает:
Loading object (dynamic) foo ... ghc.exe: foo: ....
<command line>: user specified .o/.so/.DLL could not be loaded (addDLL: could not load DLL)
Так это должно иметь какое-то отношение к статическому / динамическому связыванию? потому что я заметил, что GHC хочет загружаться .o/.so/.DLL
, но НЕТ .a
. Я действительно в замешательстве.
наконец-то получил что-то в вики: интерфейс внешней функции Cxx
[ПРАВИТЬ]
Одним из решений является использование -optl-lfoo -optl-lstdc
в .cabal
файле, а не extra-libraries
. И проблему именования можно легко решить, обернув объявление в extern "C"
:
#ifdef __cplusplus
extern "C" {
#endif
extern int foo (const char*, int);
#ifdef __cplusplus
}
#endif
Это работает в EclipseFP, потому что он использует Scion. Но он все еще терпит неудачу cabal build
.
Комментарии:
1. Поскольку вы работаете в Windows, я думаю, вам нужно изменить оператор foreign import на
foreign import stdcall "foo"
.2. @JohnL: я использую
nm
для проверки символов в файле .o после добавления__stdcall
в функцию и получаю что-то вроде этого :00000000 T __Z18fooPKci@24
. GHC по-прежнему указывает неопределенную ссылку наfoo@24
…3. @clause: этот символ искажен именем C . Вы уверены, что
foo
это объявлено внутриextern "C"
блока?4. @DerrickTurk: нет. Но сначала это в
extern "C"
. Я провел несколько экспериментов, попытался использоватьforeign import stdcall
и потерпел неудачу.5. @claude: Я попробовал ваш исходный код, и он работает для меня. Я создал библиотеку с
g -c foo.cpp; ar rcs libfoo.a foo.o; ghc ghc -lfoo Foo.hs
помощью . Это с g -4.5.0 и ghc-7.0.3. Использует ли какой-либо ваш код шаблон Haskell напрямую или через fclabels или аналогичный?