Creating a FORTRAN interface to a C function that

2019-01-08 23:34发布

I've been held up on this for about a week, now, and have searched forum after forum for a clear explanation of how to send a char* from C to FORTRAN. To make the matter more frustrating, sending a char* argument from FORTRAN to C was straight-forward...

Sending a char* argument from FORTRAN to C (this works fine):

// The C header declaration (using __cdecl in a def file):
extern "C" double GetLoggingValue(char* name);

And from FORTRAN:

! The FORTRAN interface:
INTERFACE
    REAL(8) FUNCTION GetLoggingValue [C, ALIAS: '_GetLoggingValue'] (name)
        USE ISO_C_BINDING       
        CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(*),    INTENT(IN) :: name                  
    END FUNCTION GetLoggingValue
END INTERFACE

! Calling the function:
GetLoggingValue(user_name)

When trying to use analogous logic to return a char* from C, I get problem after problem. One attempt that I felt should work is:

// The C declaration header (using __cdecl in a def file):
extern "C" const char* GetLastErrorMessage();

And the FORTRAN interface:

INTERFACE
    FUNCTION GetLastErrorMessage [C, ALIAS: '_GetLastErrorMessage'] ()
        USE ISO_C_BINDING   
        CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(255), :: GetLastErrorMessage
    END FUNCTION GetLastErrorMessage
END INTERFACE

(I can't literally use the DIMENSION(*), so I've gone oversize to 255.)

This should return a pointer to an array of 255 C-style characters - but if it does, I've been unable to convert this to a meaningful string. In practice, it returns a random set of characters, anywhere from Wingdings to the 'bell' character...

I've also attempted to return:

  • A pointer to CHARACTER(LEN=255, KIND=C_CHAR).
  • Literally CHARACTER(LEN=255, KIND=C_CHAR).
  • A INTEGER(C_SIZE_T), and tried to finesse that into a pointer to a string array.
  • A CHARACTER.
  • etc.

If anybody can give me an example of how to do this, I would be very grateful...

Best regards,

Mike

7条回答
Anthone
2楼-- · 2019-01-09 00:39

If you know the length of the string, then Pap's answer above can be greatly simplified:

function stringc2f(n, cstr) result(fstr)
integer, intent(in) :: n
type(c_ptr), intent(in) :: cstr
character(:), allocatable :: fstr
character(n, kind=c_char), pointer :: fptr
call c_f_pointer(cstr, fptr)
fstr = fptr
end function

The above function accepts a C pointer with the string and the length of the string, and returns a copy as a Fortran string.

查看更多
登录 后发表回答