Reputation: 1534
I'm trying to compile a C++ MPI wrapper to MPI Fortran library, but i fail on linking. The wrapper is compiled using
mpic++ -c my_wrapper.cc -o my_wrapper.o
my_wrapper.cc reads:
#include "mpi.h"
extern"C" {
void fortran_func_(int * comm,bool *do_init);
}
void c_func(MPI_Comm my_comm )
{
MPI_Fint fcomm;
fcomm = MPI_Comm_c2f(my_comm);
bool do_init = false;
fortran_func_(&fcomm, &do_init);
}
The library is compiled using
MPI_LINK_FLAGS = $(shell mpic++ --showme:link)
mpif90 -shared my_wrapper.o $(FORTRAN-LIBS) $(MPI_LINK_FLAGS) -o my_libc++.a
here are the linking errors:
"std::ios_base::Init::Init()", referenced from:
__static_initialization_and_destruction_0(int, int) in my_wrapper.o
"std::ios_base::Init::~Init()", referenced from:
__static_initialization_and_destruction_0(int, int) in my_wrapper.o
"vtable for __cxxabiv1::__class_type_info", referenced from:
typeinfo for MPI::Info in my_wrapper.o
typeinfo for MPI::Errhandler in my_wrapper.o
typeinfo for MPI::Win in my_wrapper.o
typeinfo for MPI::Comm_Null in my_wrapper.o
typeinfo for MPI::Group in my_wrapper.o
typeinfo for MPI::Request in my_wrapper.o
typeinfo for MPI::Status in my_wrapper.o
...
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
"vtable for __cxxabiv1::__si_class_type_info", referenced from:
typeinfo for MPI::Intercomm in my_wrapper.o
typeinfo for MPI::Graphcomm in my_wrapper.o
typeinfo for MPI::Cartcomm in my_wrapper.o
typeinfo for MPI::Intracomm in my_wrapper.o
typeinfo for MPI::Comm in my_wrapper.o
typeinfo for MPI::Grequest in my_wrapper.o
typeinfo for MPI::Prequest in my_wrapper.o
...
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
"operator delete[](void*)", referenced from:
MPI::Datatype::Get_contents(int, int, int, int*, long*, MPI::Datatype*) const in my_wrapper.o
MPI::Comm::Alltoallw(void const*, int const*, int const*, MPI::Datatype const*, void*, int const*, int const*, MPI::Datatype const*) const in my_wrapper.o
MPI::Intracomm::Create_cart(int, int const*, bool const*, bool) const in my_wrapper.o
MPI::Intracomm::Spawn_multiple(int, char const**, char const***, int const*, MPI::Info const*, int) in my_wrapper.o
MPI::Intracomm::Spawn_multiple(int, char const**, char const***, int const*, MPI::Info const*, int, int*) in my_wrapper.o
MPI::Cartcomm::Get_topo(int, int*, bool*, int*) const in my_wrapper.o
MPI::Cartcomm::Sub(bool const*) const in my_wrapper.o
...
"operator delete(void*)", referenced from:
MPI::Datatype::~Datatype() in my_wrapper.o
MPI::Datatype::~Datatype() in my_wrapper.o
MPI::Status::~Status() in my_wrapper.o
MPI::Status::~Status() in my_wrapper.o
MPI::Request::~Request() in my_wrapper.o
MPI::Request::~Request() in my_wrapper.o
MPI::Request::~Request() in my_wrapper.o
...
"operator new[](unsigned long)", referenced from:
MPI::Datatype::Get_contents(int, int, int, int*, long*, MPI::Datatype*) const in my_wrapper.o
MPI::Comm::Alltoallw(void const*, int const*, int const*, MPI::Datatype const*, void*, int const*, int const*, MPI::Datatype const*) const in my_wrapper.o
MPI::Intracomm::Create_cart(int, int const*, bool const*, bool) const in my_wrapper.o
MPI::Intracomm::convert_info_to_mpi_info(int, MPI::Info const*) in my_wrapper.o
MPI::Cartcomm::Get_topo(int, int*, bool*, int*) const in my_wrapper.o
MPI::Cartcomm::Sub(bool const*) const in my_wrapper.o
MPI::Cartcomm::Map(int, int const*, bool const*) const in my_wrapper.o
...
"operator new(unsigned long)", referenced from:
MPI::Intracomm::Clone() const in my_wrapper.o
MPI::Cartcomm::Clone() const in my_wrapper.o
MPI::Graphcomm::Clone() const in my_wrapper.o
MPI::Intercomm::Clone() const in my_wrapper.o
"___cxa_pure_virtual", referenced from:
vtable for MPI::Comm in my_wrapper.o
"___gxx_personality_v0", referenced from:
Dwarf Exception Unwind Info (__eh_frame) in my_wrapper.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
I could not find any example how to do such things (mixed Fortran/C++ with MPI) so I ask here in a hope that it will be useful for somebody else at some point.
P.S.
If i try to compile it with mpic++
:
MPIF_LINK_FLAGS = $(shell mpif90 --showme:link)
mpic++ -shared my_wrapper.o $(FORTRAN-LIBS) $(MPIF_LINK_FLAGS) -o $@
I miss a lot of symbols from $(FORTRAN-LIBS) which i don't when i link with mpif90
.
So i guess i better add those missing libraries to Fortran linker.
I use Open MPI: 1.6
if it matters.
EDIT1: by adding those to mpif90 linking everything compiles:
-L/opt/local/lib/gcc47/ -lstdc++
Indeed, some standard C++ stuff was missing
Upvotes: 3
Views: 1507
Reputation: 48692
It seems you are linking using the FORTRAN linker. It knows nothing about the C++ standard library, so all of the C++ standard library (such parts of std::ios_base
) will be "undefined symbols". You need to alter your link command, to add the C++ standard library.
As your composite is neither entirely FORTRAN nor entirely C++, neither the FORTRAN nor the C++ linker are entirely appropriate. You might want to consider using ld
directly. In that case, you would have to list the C++ standard library and the FORTRAN standard library as libraries to link with.
Upvotes: 2