Я пытаюсь создать привязку Haskell для Xapian. Но когда GH C пытается связать привязку, он терпит неудачу из-за некоторых проблем со связью.
Вот часть файла заголовка:
// file: cbits/libhsxapian.h
#ifdef __cplusplus
extern "C" {
#endif
Xapian::Document* xapian_document_C0();
void xapian_document_D0(Xapian::Document* doc);
Xapian::SimpleStopper* xapian_simplestopper_C0();
void xapian_simplestopper_D0(Xapian::SimpleStopper* stopper);
#ifdef __cplusplus
}
#endif
И соответствующий исходный файл:
// file: cbits/libhsxapian.cpp
#include <xapian.h>
#include "hsxapian.h"
Xapian::Document* xapian_document_C0() {
return new Xapian::Document();
}
void xapian_document_D0(Xapian::Document* doc) {
delete doc;
}
Xapian::SimpleStopper* xapian_simplestopper_C0() {
return new Xapian::SimpleStopper();
}
void xapian_simplestopper_D0(Xapian::SimpleStopper* stopper) {
delete stopper;
}
И исходный файл Haskell, содержащий код FFI:
-- file: src/Bindings/Xapian.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Bindings.Xapian where
import Foreign
import Foreign.C
type DocumentPtr = Ptr ()
foreign import ccall "hsxapian.h xapian_document_C0"
xapian_document_C0 :: IO DocumentPtr
foreign import ccall "hsxapian.h &xapian_document_D0"
xapian_document_D0 :: FunPtr (DocumentPtr -> IO ())
type StopperPtr = Ptr ()
foreign import ccall "hsxapian.h xapian_simplestopper_C0"
xapian_simplestopper_C0 :: IO StopperPtr
foreign import ccall "hsxapian.h &xapian_simplestopper_D0"
xapian_simplestopper_D0 :: FunPtr (StopperPtr -> IO ())
Среди других параметров файл cabal содержит:
include-dirs:
cbits
cxx-sources:
cbits/hsxapian.cpp
extra-libraries:
stdc++
Когда я пытаюсь скомпилировать это package Я получаю следующее сообщение об ошибке:
<command line>: /home/user/hsxapian/.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.0.1.0/build/libHShsxapian-0.1.0.0-6mEQUi65qY9HKkEuYL7SJz-ghc8.8.3.so: undefined symbol: _ZTVN6Xapian13SimpleStopperE
Очевидно GH C не может связать исполняемый файл, содержащийся в пакете, с библиотекой. Однако, используя nm
, я могу проверить, что символ присутствует в libxapian
:
$ nm -D /usr/lib/libxapian.so | grep _ZTVN6Xapian13SimpleStopperE
0000000000226cf0 V _ZTVN6Xapian13SimpleStopperE
$ nm -D -C /usr/lib/libxapian.so | grep 0000000000226cf0
0000000000226cf0 V vtable for Xapian::SimpleStopper
Интересно, что если я удалю xapian_simplestopper_C0
из заголовка, исходники C ++ и Haskell все компилируются и связываются как и ожидалось. И если я снова добавлю xapian_document_C0
, он все равно компилируется и тоже связывается.
Итак, мои вопросы:
Почему GH C задыхается на SimpleStopper
, но не на Document
?
SimpleStopper кажется обычным классом C ++, например Document .
Почему второй запуск завершился успешно?
Я ожидал, что он завершится неудачно на этапе связывания с тем же сообщением об ошибке. Разве исполняемый файл не связывается снова или GH C каким-то образом может найти отсутствующий символ?
Как отладить такую проблему связывания?
Я не нашел в Интернете никаких ценных ресурсов. Есть ли какие-то флаги, которые я пропустил в руководстве пользователя GH C? Кроме того, мне известно следующее: