Open MPI logo

Open MPI User's Mailing List Archives

  |   Home   |   Support   |   FAQ   |   all Open MPI User's mailing list

Subject: Re: [OMPI users] Can't compile C++ program with extern "C" { #include mpi.h }
From: Adam C Powell IV (hazelsct_at_[hidden])
Date: 2008-01-13 16:02:51

Hi again,

Sorry about the hiatus; I thought "Great, my OMPI_SKIP_CXX hack works"
and didn't check to see your reply, even though it came right away.

On Tue, 2008-01-01 at 11:07 -0700, Brian Barrett wrote:
> On Jan 1, 2008, at 12:47 AM, Adam C Powell IV wrote:
> > On Mon, 2007-12-31 at 20:01 -0700, Brian Barrett wrote:
> >>
> >>
> >> Yeah, this is a complicated example, mostly because HDF5 should
> >> really be covering this problem for you. I think your only option at
> >> that point would be to use the #define to not include the C++ code.
> >>
> >> The problem is that the MPI standard *requires* mpi.h to include both
> >> the C and C++ interface declarations if you're using C++. There's no
> >> way for the preprocessor to determine whether there's a currently
> >> active extern "C" block, so there's really not much we can do. Best
> >> hope would be to get the HDF5 guys to properly protect their code
> >> from C++...
> >
> > Okay. So in HDF5, since they call MPI from C, they're just using
> > the C
> > interface, right? So should they define OMPI_SKIP_MPICXX just in case
> > they're #included by C++ and using OpenMPI, or is there a more MPI
> > implementation-agnostic way to do it?
> No, they should definitely not be disabling the C++bindings inside
> HDF5 -- that would be a situation worse than the current one.
> Consider the case where an application uses both HDF5 and the C++ MPI
> bindings. It includes hdf5.h before mpi.h. The hdf5.h includes
> mpi.h, without the C++ bindings. The application then includes mpi.h,
> wanting the C++ bindings. But the multiple inclusion protection in
> mpi.h means nothing happens, so no C++ bindings.

I agree, that would be a problem...

> My comment about HDF5 was that it would be easiest if it protected its
> declarations with extern "C" when using C++. This is what most
> packages that might be used with C++ do, and it works pretty well.
> I'd actually be surprised if modern versions of HDF5 didn't already do
> that.
> Now that it's not New Years eve, I thought of what's probably the
> easiest solution for you. Just include mpi.h (outside your extern "C"
> block) before hdf5.h. The multiple inclusion protection in mpi.h will
> mean that the preprocessor removes everything from the mpi.h that's
> included from hdf5.h. So the extern "C" around the hdf5.h shouldn't
> be too much of a problem.

That almost works. But not quite. :-(

If I put that in my C++ files or headers, that would be fine.
Unfortunately, the program I'm porting has:

#include <hdf5.h>

extern "C" { #include "A.h" }

And then C.hxx, D.cxx, etc. all include B.hxx, and E.h and F.c include
A.h. So if I just add "#include <mpi.h>" to A.h before hdf5, I have the
same problem: #including <mpi.h> within an extern "C" block.

The only way to work around this is to patch B, C, D, E and F. Very bad.
It shouldn't have to be this way.

Here's a way to make it work, but it requires a patch to OpenMPI mpi.h:
--- /usr/include/mpi/mpi.h~ 2008-01-10 17:26:15.000000000 -0500
+++ /usr/include/mpi/mpi.h 2008-01-13 15:57:45.000000000 -0500
@@ -1770,6 +1770,8 @@

+#endif /* OMPI_MPI_H */
  * Conditional MPI 2 C++ bindings support. Include if:
  * - The user does not explicitly request us to skip it (when a C++ compiler
@@ -1783,5 +1785,3 @@
 #include "openmpi/ompi/mpi/cxx/mpicxx.h"
-#endif /* OMPI_MPI_H */

Then hdf5.h, or this app's A.h, or whoever, can do:
#include <mpi.h> or <hdf5.h> or <A.h> etc.
and the C++ programs which include this will not miss their C++ headers,
because they won't be inside the OMPI_MPI_H #ifdef protection. But they
also won't get them twice, because they'll be in the MPIPP_H #ifdef.

Do you have any other ideas? Or will this or something like it be
necessary to protect against arbitrarily nested #includes from C++
extern "C" blocks, without stepping on the C++ prototypes?

Thanks again for your help,

GPG fingerprint: D54D 1AEE B11C CE9B A02B  C5DD 526F 01E8 564E E4B6
Engineering consulting with open source tools