首页 > 解决方案 > 带有 MPI 前向声明的标头

问题描述

我正在使用这样的简短 MPI 包装器:

#ifndef INC_MyLib_MPIWRAPPER_H
#define INC_MyLib_MPIWRAPPER_H

#include <mpi.h>


/* libMyLib MPI struct & macros */
namespace libMyLib{
    extern int mpi_rank;
    extern int mpi_nranks;
    extern int mpi_msg;
    extern int mpi_msg_;
    extern MPI_Comm mpi_active_comm;
}

#define MPI_INIT MPI_Init(&argc, &argv); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_INIT_NULL MPI_Init(nullptr, nullptr); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_FINISH MPI_Finalize( );

#define MPI_INTERRUPT libMyLib::mpi_msg = 1; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);
#define MPI_ERROR_CHECK libMyLib::mpi_msg = 0; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);; if( libMyLib::mpi_msg_ > 0 ){throw std::runtime_error(" eror " );}

#endif //INC_MyLib_MPIWRAPPER_H

我想mpi.h在这里摆脱依赖,所以我尝试添加这样的MPI类型的前向声明:

#ifndef INC_MyLib_MPIWRAPPER_H
#define INC_MyLib_MPIWRAPPER_H

#include <mpi.h>

/* MPI forward declarations to remove MPI header dependency from API */
typedef int MPI_Comm;
typedef int MPI_Datatype;
#define MPI_INT ((MPI_Datatype)0x4c000405)

typedef int MPI_Op;
#define MPI_SUM     (MPI_Op)(0x58000003)
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);

#if defined(HAVE_VISIBILITY)
#define MPICH_API_PUBLIC __attribute__((visibility ("default")))
#else
#define MPICH_API_PUBLIC
#endif
int MPI_Finalize(void) MPICH_API_PUBLIC;
int MPI_Comm_size(MPI_Comm comm, int *size) MPICH_API_PUBLIC;
int MPI_Comm_rank(MPI_Comm comm, int *rank) MPICH_API_PUBLIC;
int MPI_Init(int *argc, char ***argv) MPICH_API_PUBLIC;

/* libMyLib MPI struct & macros */
namespace libMyLib{
    extern int mpi_rank;
    extern int mpi_nranks;
    extern int mpi_msg;
    extern int mpi_msg_;
    extern MPI_Comm mpi_active_comm;
}

#define MPI_INIT MPI_Init(&argc, &argv); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_INIT_NULL MPI_Init(nullptr, nullptr); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_FINISH MPI_Finalize( );

#define MPI_INTERRUPT libMyLib::mpi_msg = 1; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);
#define MPI_ERROR_CHECK libMyLib::mpi_msg = 0; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);; if( libMyLib::mpi_msg_ > 0 ){throw std::runtime_error(" eror " );}

#endif //INC_MyLib_MPIWRAPPER_H

问题是,在一个代码中,我需要将此包装器与真正的mpi.h标头结合起来,并且出现如下错误:

/usr/bin/ld: ../../lib/liblibMyLib.a(Reader.cpp.o): in function `libMyLib::Reader::read()':
Reader.cpp:(.text+0x10f3): undefined reference to `MPI_Allreduce(void const*, void*, int, int, int, int)'
/usr/bin/ld: Reader.cpp:(.text+0x1764): undefined reference to `MPI_Allreduce(void const*, void*, int, int, int, int)'
collect2: error: ld returned 1 exit status

虽然我能理解,但我很好奇是否有任何方法,如果需要,如何使前向声明能够使用包装器并将其与mpi.h标头结合起来?

标签: c++headerdependencies

解决方案


我不知道你为什么要这样做,或者它是否能正常工作,但你现在观察到的特定错误是因为 MPI 是一个 C 库。

C++ 将 C 实体与 C++ 实体分开处理。因此,如果您MPI_Allreduce在 C++ 代码中声明一个函数,它所引用的函数MPI_Allreduce与您在 C 代码中使用相同声明时所获得的函数不同。

为了使名称引用 C 实体,您必须使用 C 语言链接声明它,这是通过

extern "C" {
    // declarations go here
}

您可以查看mpi.h它是否执行相同的操作。


推荐阅读