I read sometime ago on a thread labeled "C interface yields error #8532: A character dummy argument with length other than 1 is not interoperable " where Steve had mentioned to the person to use the following syntax to pass C a string as a character of strings: character, dimension(*). In porting to 2012, I am seeing the issues as mentioned in that post from the following bound fortran function:
Integer Function getErrorMsg(errMsg, maxChar) bind((C,name="GetErrorMessage")
CHARACTER*(maxChar), dimension(1) =>> Changed to CHARACTER, DIMENSION(*) (compiles successfully)
My questions are:
1) Why use an * versus a : ? I thought since the array is passed into the function, it should use a : to assume the size of the array being passed in.(i.e. I understand : will cause an error but I guess I am unclear on proper uses of an * versus a :
2) What is the best practice to pass strings between FORTRAN and C? The old code defined the string array with a max chars, but I have seen others append a nul to emulate a C string. I guess as long as the called code knows what to expect, it should not matter.
* is "assumed-size" where nothing gets passed for the bounds of the array. : is "assumed-shape" where the caller passes in bounds information that the called routine picks up. The method for passing bounds info is implementation-specific and therefore this is not interoperable with C - at least until Fortran 2015.
In Fortran 2003 (and 2008), the only way to declare an interoperable character argument is as a fixed or assumed-size array of single characters. The standard carves out an exemption for argument consistency here allowing you to pass an arbitrary-length character item to a dummy declared as an array of characters. Unfortunately, the reverse is not true - in these standards there is no support for C passing a "char *" array to Fortran where it is declared as CHARACTER with a length other than 1. Typically you would have to loop through the array looking for the trailing NUL to determine the length - error prone.
Fortran 2015, through the "Further Interoperability with C" Technical Specification TS29113, greatly expands what you can pass between Fortran and C to include assumed-shape arrays, allocatables, pointers and passed-length character dummy arguments. The catch is that such arguments are passed by "C descriptor", a concept of the Fortran standard that specifies a data structure to be passed between the languages. A Fortran compiler provides an ISO_Fortran_binding.h file that declares data structures, typedefs, functions and macros to be used in this expanded interopoerability. I will be writing a Doctor Fortran post on this soon.
The C descriptor means that you don't have to rely on compiler-specific (and sometimes undocumented) hacks in C code to pass what Fortran expects. Your Fortran code doesn't ever see a C descriptor - the compiler handles that for you behind the scenes.
Intel Fortran 16 (Parallel Studio XE 2016) fully supports the TS29113 features. See the attached presentation for more.509355
Thanks Steve. I did see your presentation on these capabilities, though it was the 2016 version of Fortran which fully implemented the 2008 spec to include the submodule specification (something we definitely could use to avoid numerous circular reference issues we have had in the past).
INDEX is useful only when you have a character string with length greater than 1. But yes, once you have such a variable INDEX is the right way to get the NUL-terminated length.