I do either
… And yes, to be safer the string should not be modified while in the C part of the code (or at least the original length should be keep along).
(about the CFI descriptor approach):
Indeed, I’ve checked the “Modern Fortran Explained” (F2018 edition) and they explicitly say that passing an assumed length string actually passes a cfi_cdesc_t*. Although they do not mention the deferred lenght case, it looks logical that this works also with them. In practice the ->elem_len member is the Fortran length of the string and ->rank is 0.
This is probably the cleanest way.