Связывание исполняемого файла Haskell со статической библиотекой, написанной на C , получило «неопределенную ссылку`

#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 или аналогичный?