1

I have been trying to pass a character array from C++ to a Fortran subroutine but it seems like Fortran does not receive characters properly. I have been searching the web to find a solution but proposed ideas seem to be too complicated. An interesting (and concise) solution was proposed by Steve at Intel Fortran Forum but I cannot get it work in my code. So, I appreciate any suggestion to help me out to resolve this issue.

The following function is my C++ routine that makes call to fortran subroutines:

extern "C" void __stdcall F_VALIDATE_XML(const char* buffer, int len);
void CUDMEditorDoc::OnValidateXML()
{
    CString fileName = "test.udm";
    const char* buffer = fileName.GetBuffer();
    int len = fileName.GetLength();
    F_VALIDATE_XML(buffer, len);
}

And here is the Fortran subroutine that is supposed to receive character array:

subroutine validate_xml(file_name, len)
!DEC$ ATTRIBUTES DECORATE, STDCALL, ALIAS:"F_VALIDATE_XML" :: validate_xml

use xml_reader_structure
use, intrinsic :: ISO_C_Binding

integer(C_INT), value, intent(in) :: len
character(len, kind=C_CHAR), intent(in) :: file_name

integer  :: i
i = 1
end subroutine validate_xml

In debug mode and when the program has stopped at line (i = 1), I hover mouse over file_name to see its contents but the Watch window says that it cannot find file_name symbol (although len is correctly passed). Also, if I watch file_name(1:8) in watch window, still I don't get the original character arrays. I believe there is something wrong with the way I pass parameters to Fortran but chances are Watch Window is not correct.

I appreciate any help that could shed some lights here. Thanks

missimer
  • 4,022
  • 1
  • 19
  • 33
Pouya
  • 1,871
  • 3
  • 20
  • 25

1 Answers1

4

You fell into the trap which is caused by saying (even on Stack Overflow in heavily upvoted answers) that you should use ISO C binding to construct interoperable subroutines.

That is wrong, using the iso_c_binding module does not make the procedure interoperable and does not change the calling conventions.

The other, separate and equally important, feature in Fortran 2003 to C interoperability is the bind(C) attribute.

Notice, that Steve Lionel has it in the linked example. You should have

   subroutine validate_xml(file_name, len) bind(C, name="F_VALIDATE_XML")

The bind(C) changes the calling conventions in several subtle ways and the largest difference is for character strings, which normally pass the length in a hidden argument, but not in interoperable procedures.