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

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.