FFI 导入的 MPI 常量的 GHCi 链接器错误(通过 c2hs)
GHCi linker error with FFI-imported MPI constants (via c2hs)
我正在通过重写绑定来弄清楚 haskell-mpi 是如何工作的。我正在尝试重新使用通过安装 PETSc(工作正常)设置的 MPICH 安装。
问题:make main
在 GHCi 中为我提供了一个正确的模块,但是当我请求计算 commWorld 时,链接器抱怨它找不到 MPI_COMM_WORLD 符号(但是它在 makefile 的范围内)。
我做错了什么?提前致谢
错误:
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_
生成文件:
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)
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 有一些魔法可以为您做到这一点。
我刚刚了解到 CApiFFI
扩展(自 GHC 7.6 起)允许您不仅导入实际上可能是宏的 C 级 "functions",还允许导入实际上可能是宏的 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 处的文档。
我正在通过重写绑定来弄清楚 haskell-mpi 是如何工作的。我正在尝试重新使用通过安装 PETSc(工作正常)设置的 MPICH 安装。
问题:make main
在 GHCi 中为我提供了一个正确的模块,但是当我请求计算 commWorld 时,链接器抱怨它找不到 MPI_COMM_WORLD 符号(但是它在 makefile 的范围内)。
我做错了什么?提前致谢
错误:
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_
生成文件:
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)
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 有一些魔法可以为您做到这一点。
我刚刚了解到 CApiFFI
扩展(自 GHC 7.6 起)允许您不仅导入实际上可能是宏的 C 级 "functions",还允许导入实际上可能是宏的 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 处的文档。