【问题标题】:GHCi linker error with FFI-imported MPI constants (via c2hs)带有 FFI 导入的 MPI 常量的 GHCi 链接器错误(通过 c2hs)
【发布时间】:2015-07-16 19:40:06
【问题描述】:

我正在通过重写绑定来弄清楚 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)

【问题讨论】:

    标签: c haskell mpi petsc c2hs


    【解决方案1】:
    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 有一些魔法可以为你做到这一点。

    【讨论】:

    • 我在想 {# enum ... #} 宏。然而,上面的定义取自原始绑定库。但是我不确定,因为我还不能让haskell-mpi 正确构建。谢谢你现在
    • haskell-mpi 和我建议的一样,参见文件src/cbits/constants.c
    • 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 是一个函数宏,接下来的所有行都是..具体类型?
    • C2HS 中还有一个 {#const ...#} 东西,但它只在#define 右侧的内容扩展为看起来像 Haskell 中的常量的情况下才真正起作用以及在 C 中(所以“#define ABC 123”和“{#const ABC#}”可以正常工作)。在这种情况下,执行 "{#const MPI_COMM_WORLD#}" 会将 C 代码 "(MPI_Comm) (void *) &ompi_mpi_comm_world" 拼接到您的 Haskell 代码中,这根本没有用!我认为里德的建议绝对是要走的路。
    【解决方案2】:

    我刚刚了解到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 上的文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-23
      • 1970-01-01
      • 2014-07-19
      • 2016-09-19
      • 2013-10-08
      • 2015-09-09
      • 1970-01-01
      相关资源
      最近更新 更多