Wrapping C library that uses MPI_Comm in its public interface


#1

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.


#2

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.


#3

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)


#4

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

IIRC bindgen respects the C_INCLUDE_PATH environment variable.


#5

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?


#6

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.