Связывание Haskell с обернутой библиотекой C ++ - PullRequest
2 голосов
/ 16 июня 2020

Я пытаюсь создать привязку 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, он все равно компилируется и тоже связывается.

Итак, мои вопросы:

  1. Почему GH C задыхается на SimpleStopper, но не на Document?

    SimpleStopper кажется обычным классом C ++, например Document .

  2. Почему второй запуск завершился успешно?

    Я ожидал, что он завершится неудачно на этапе связывания с тем же сообщением об ошибке. Разве исполняемый файл не связывается снова или GH C каким-то образом может найти отсутствующий символ?

  3. Как отладить такую ​​проблему связывания?

    Я не нашел в Интернете никаких ценных ресурсов. Есть ли какие-то флаги, которые я пропустил в руководстве пользователя GH C? Кроме того, мне известно следующее:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...