Wrapping C library that uses MPI_Comm in its public interface

I've generated raw rust bindings to a C header for use as a -sys crate, but one function is making me uncomfortable; it takes an MPI_Comm by value. Unfortunately for me, there's no mpi-sys crate; perhaps due in part to the same issue I'm about to discuss.

So, what is an MPI_Comm? Glad you asked! It's part of the MPI protocol and, to the best of my knowledge, it's... not specified. What I mean is, it can vary between MPI implementations. Some common ones:

typedef struct comm_info* MPI_Comm;  // used by OpenMPI
typedef int MPI_Comm; // used by... things that aren't OpenMPI

What's the common approach to handling this? To my understanding -sys crates should ideally make no design decisions at all and simply present the C API as it is; but I don't see how that can be done here.

1 Like

I don't quite understand the concern. MPI implementations are not binary compatible, so I don't see why passing MPI_Comm by value is a problem. In rsmpi, MPI_Comm is simply defined as a type alias for whatever underlying type the MPI implementation uses, which is detected at compile time through bindgen.

If my concerns sound dumb they probably are; I'm a bit out of my depth here. The majority of my experience with library linking is only from the perspective of me as a user trying to build and install programs. I must confess I don't see what difference binary compatibility makes here.

IIRC I had too much trouble getting bindgen to locate MPI headers at build time, so I decided to generate by running bindgen manually and then deleting all of the MPI stuff. Now that I'm taking a second look at things it appears that I could probably copy notes from how rsmpi does it, and just leave the MPI stuff in there.

I gather that there is some sort of single linking rule, so I'm concerned that if I link MPI then it could prevent a crate from simultaneously depending on both my crate and, say, rsmpi or mpi. As another alternative, I guess I could depend on rsmpi or mpi, but both feel like a heavier dependency than I would like to have.


(well, okay, heavy isn't the right term; but both provide Rust wrappers around the library when all I want to do is link it. also, the single-link rule would seem to imply that rsmpi and mpi themselves are mutually exclusive)


(:laughing: I just realized mpi and rsmpi are the same crate)

I had too much trouble getting bindgen to locate MPI headers at build time

IIRC bindgen respects the C_INCLUDE_PATH environment variable.

1 Like

I've finally gotten around to making the change to adopt bindgen at build time.

Here is my sys crate.

You will see that I have added a dumb safety feature to replace MPI_Comm with an empty enum by default. This is because my crate currently only supports prebuilt, shared object forms of the library I am wrapping, meaning there is a possibility that the mpi.h found on the system path could diverge from the one that the library was built against.

Does this sound reasonable?

Empty enum should be fine, as long as you don't handle MPI_Comm by value – which basically means there's almost nothing you can do with it, since the MPI API expects it by value in most places.