Ошибка компоновщика GHCi с константами MPI, импортированными FFI (через c2hs)

Я выясняю, как работает haskell-mpi, переписывая привязку. Я пытаюсь повторно использовать установку MPICH, которая была установлена ​​путем установки PETSc (которая работает нормально). Вопрос: make main дает мне правильный модуль в GHCi, но когда я запрашиваю вычисление commWorld, компоновщик жалуется, что не может найти символ MPI_COMM_WORLD (который, однако, входит в область действия make-файла).

Что я делаю не так? заранее спасибо

ошибка:

ByteCodeLink: can't find label
During interactive linking, GHCi couldn't find the following symbol:
   MPI_COMM_WORLD

Основные.chs :

type MPIComm = {# type MPI_Comm #} 
newtype Comm = MkComm { fromComm :: MPIComm } deriving (Eq, Show)
foreign import ccall "&MPI_COMM_WORLD" commWorld_ :: Ptr MPIComm
foreign import ccall "&MPI_COMM_SELF" commSelf_ :: Ptr MPIComm

commWorld, commSelf :: Comm
commWorld = MkComm <$> unsafePerformIO $ peek commWorld_
commSelf = MkComm <$> unsafePerformIO $ peek commSelf_

make-файл:

PETSC_DIR_ARCH = ${PETSC_DIR}/arch-darwin-c-debug
PETSC_DIR_ARCH_INCLUDE = ${PETSC_DIR_ARCH}/include

main : 
    c2hs Main.chs -C -I${PETSC_DIR_ARCH}/include -C -I${PETSC_DIR}/include 
    ghci Main.hs -L${PETSC_DIR_ARCH}/lib -lpetsc -lmpich

мпи.ч

 typedef int MPI_Comm;
 #define MPI_COMM_WORLD ((MPI_Comm)0x44000000)
 #define MPI_COMM_SELF  ((MPI_Comm)0x44000001)

person ocramz    schedule 06.05.2015    source источник


Ответы (2)


foreign import ccall "&MPI_COMM_WORLD" commWorld_ :: Ptr MPIComm

означает, что commWorld_ будет указателем на переменную MPI_COMM_WORLD. Но на самом деле MPI_COMM_WORLD это не переменная, это макрос CPP, так что это не та штука, у которой вообще есть адрес, и об этом вам говорит ошибка компоновщика.

Я бы, вероятно, добавил файл C с определением вроде

const MPI_Comm hs_MPI_COMM_WORLD = MPI_COMM_WORLD;

и импортируйте это так, как вы это сделали. Возможно, у c2hs есть какая-то магия, которая сделает это за вас.

person Reid Barton    schedule 06.05.2015
comment
Я думаю о макросе {# enum ... #}. Однако приведенное выше определение взято из исходной библиотеки привязок. Однако я не уверен, потому что я еще не могу заставить haskell-mpi правильно собраться. Спасибо, пока - person ocramz; 06.05.2015
comment
haskell-mpi делает то же самое, что я предложил, см. файл src/cbits/constants.c. - person Reid Barton; 06.05.2015
comment
src/cbits/constants.c начинается: #define MPI_CONST(ty, name, defn) ty name = defn; MPI_CONST (MPI_Datatype, mpi_char, MPI_CHAR) MPI_CONST (MPI_Datatype, mpi_wchar, MPI_WCHAR) ... #define - это макрос функции, а все следующие строки - это... конкретные типы? - person ocramz; 06.05.2015
comment
В C2HS также есть элемент {#const ...#}, но он действительно работает только в тех случаях, когда то, что находится справа от #define, расширяется до чего-то, что выглядит как константа как в Haskell, так и в C (поэтому # определить ABC 123 и {#const ABC#} работает нормально). В этом случае выполнение {#const MPI_COMM_WORLD#} встраивает код C (MPI_Comm) (void *) &ompi_mpi_comm_world в ваш код Haskell, что совершенно бесполезно! Я думаю, что предложение Рида, безусловно, правильный путь. - person Ian Ross; 15.05.2015

Я только что узнал, что расширение CApiFFI (начиная с GHC 7.6) позволяет вам импортировать не только «функции» уровня C, которые на самом деле могут быть макросами, но и значения уровня C, которые могут быть макросами. Таким образом, вы должны быть в состоянии написать

{-# LANGUAGE CApiFFI #-}

type MPIComm = {# type MPI_Comm #} 
foreign import capi "mpi.h value MPI_COMM_WORLD" :: MPIComm

без необходимости писать дополнительный файл C (GHC сделает это за вас).

См. документацию по адресу https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ffi.html#ffi-capi.

person Reid Barton    schedule 02.06.2015