The accepted answer contains two errors (it passes the wrong value as the length of the string to GETCWD and leaves it in C_NULL_CHAR ). This answer corrects these errors and makes the interface more convenient to use in Fortran.
The basic idea is the same: call getcwd or _getcwd using C, and call the C shell using the Fortran C interaction functions. On the Fortran side, the wrapper routine is used to handle the length of the string, so it does not need to be passed explicitly.
In addition, C_INT and C_CHAR optional, as are the default integers and default characters that C_CHAR on the Fortran side (although in practice I donβt know a single system where C_CHAR and char are by default). The shell also converts them. In addition, the string returned from C contains the trailing C_NULL_CHAR , which must be deleted so that the string can be used on the Fortran side.
Code C:
#ifdef _WIN32 #include <direct.h> #define GETCWD _getcwd #else #include <unistd.h> #define GETCWD getcwd #endif /* Return 0 on success, 1 on error. */ int getCWDHelper(char *str, int len) { return GETCWD(str, len) != str; }
Fortran Code:
module cwd use iso_c_binding, only: C_INT, C_CHAR, C_NULL_CHAR implicit none private public :: getCWD interface function getCWDHelper(str, len) bind(C, name="getCWDHelper") use iso_c_binding, only: C_INT, C_CHAR integer(kind=C_INT) :: getCWDHelper character(kind=C_CHAR), intent(out) :: str(*) integer(kind=C_INT), value :: len end function getCWDHelper end interface contains ! Writes the current working directory path into str. ! Returns 0 on success, or 1 on error. function getCWD(str) integer :: getCWD character(*), intent(out) :: str integer :: i, length character(len=len(str), kind=C_CHAR) :: str_copy ! Call the C helper, passing the length as the correct int kind getCWD = getCWDHelper(str_copy, len(str_copy, kind=C_INT)) if (getCWD /= 0) then str = '' ! Error, clear the string return end if ! Copy the C_CHAR string to the output string, ! removing the C_NULL_CHAR and clearing the rest. length = index(str_copy, C_NULL_CHAR) - 1 do i = 1, length str(i:i) = char(ichar(str_copy(i:i))) end do str(length+1:) = '' end function getCWD end module
Test code:
program test use cwd, only: getCWD implicit none character(len=255) :: path integer :: error error = getCWD(path) print *, error if (error == 0) print *, path end program
By making the return value placementable and circular to get enough size, we leave it to the reader as an exercise.