2015-05-06 1 views
2

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

Что я делаю неправильно? Заранее спасибо

ошибка:

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

Main.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_ 

Makefile:

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 

mpi.h

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

ответ

3
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 есть волшебство, которое сделает это за вас.

+0

Я думаю о макросе {# enum ... #}. Однако вышеприведенное определение взято из исходной библиотеки привязки. Однако я не уверен, потому что я не могу получить 'haskell-mpi', чтобы правильно строить. Спасибо, что сейчас – ocramz

+1

'haskell-mpi' делает то же, что и я предложил, см. Файл' src/cbits/constants.c'. –

+0

'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 является функцией макро и все последующие строки are..concrete типы? – ocramz

1

Я только что узнал, что расширение 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.