Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28494 Discussions

how Hidden length parameter is calculated...

Roberto_Sartori
Beginner
505 Views

Hi,

suppose my subroutine declared as follow:

SUBROUTINE mySub(myString)

CHARACTER(nChar), INTENT(OUT) :: myString(*)

...

END SUBROUTINE

the hidden length is the number of total chars (so number of elements of myString * nChar) or the number of elements in myString only?

0 Kudos
8 Replies
Steven_L_Intel1
Employee
505 Views

The hidden length passed in is the length of an individual element. You really should declare the argument as CHARACTER(*) or else you may create subtle run-time errors if the length passed in is not nChar,

0 Kudos
Roberto_Sartori
Beginner
505 Views

The hidden length passed in is the length of an individual element. You really should declare the argument as CHARACTER(*) or else you may create subtle run-time errors if the length passed in is not nChar,

thanks, but this means that fortran cannot automatically detect the length of myString, it can detect only the length of the single element myString(i).

am I correct?

0 Kudos
Steven_L_Intel1
Employee
505 Views

Only the length of an individual element is passed in your example. If you want the array bounds passed, then declare the argument to have dimension (:) and provide an explicit interface for the procedure to the caller.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
505 Views
Quoting - Roberto Sartori

thanks, but this means that fortran cannot automatically detect the length of myString, it can detect only the length of the single element myString(i).

am I correct?

Fortran does not allow string arrays of heterogenous length: all elements of myString(*) must be of the same length.

But I have a hunch that you have a misconception concerning Fortran strings: basically, they're fixed-length buffers. In your declaration, it is the caller which instantiates the storage and passes the length (by value, by the way), and the callee can just read and use that length, but cannot alter it. Along the lines of C routines such as strcpy_s or strncpy.

Such design might be a bit less flexible than the C one, but it's safe from infamous buffer overflows.

Fortran 2003 brings character strings of allocatable length, but they're a fairly different beast, at least on low-level implementation. I'm not sure if they're implemented in IVF 11 though.

0 Kudos
Steven_L_Intel1
Employee
505 Views
Quoting - Jugoslav Dujic

Fortran 2003 brings character strings of allocatable length, but they're a fairly different beast, at least on low-level implementation. I'm not sure if they're implemented in IVF 11 though.

Not in 11.0.

0 Kudos
garylscott1
Beginner
505 Views

Not in 11.0.

Are they particularly difficult or just lower priority?

0 Kudos
Steven_L_Intel1
Employee
505 Views

Just a lot of work. Next release.

0 Kudos
John_P_1
Beginner
505 Views

Actually we worked on passing SafeArrays from VB6 to a fortran DLL back in 2003.

Fortran passes the string and a hidden length argument by default. The length argument is always passed by value and is located immediately following the address of the character string. Compiler directives control how strings are passed.

Basic must pass the string by value to Fortran subroutines and additionally pass an integer equal to the length of the character string in the argument list. Passing strings by value dereferences the structure and passes only the location of the string, which is what Fortran expects.

In the Fortran DLL:

!DEC$ ATTRIBUTES STDCALL ::
!DEC$ ATTRIBUTES REFERENCE ::

The STDCALL directive ignores hidden arguments. Activating the REFERENCE directive additionally forces the string to be passed by reference. Combined together the result is a string passed by reference with no hidden length arguments.
The side effect of the STDCALL directive is that it forces the name of the Fortran subroutine to be lowercase. The name specified in the Basic program must be lowercase.

Declare Sub Example lib Fortran.dll alias example ( _
ByVal LengthOfString as Long, _
ByVal TestString as String _
)
Dim TestString as String
TestString = This is a test.
LengthofString = len( TestString )
Example LengthOfString, TestString


For the Fortran subroutine in Fortran.dll note the case of names:
Subroutine Example( Length, Str )
!DEC$ ATTRIBUTES DLLEXPORT :: Example
!DEC$ ATTRIBUTES STDCALL :: Example
!DEC$ ATTRIBUTES REFERENCE :: Str
Integer(4), intent(IN) :: Length
Character(Length), intent(INOUT) :: Str
Str = Echo that.
Return
End

Example is forced to lowercase by the STDCALL directive. Str is passed by reference with no hidden arguments. Note, however, that the Basic program must pass the string by value. This is not a conflict: the Fortran string is passed by reference with no hidden arguments and the Basic string is dereferenced so that only the location is known. These are equivalent, even though the words used in both languages is not identical.
The side effect of the STDCALL directive is to force all dummy arguments to be passed by value. To force a pass by reference for other dummy arguments, list those arguments in a REFERENCE directive. This would be necessary for passing a floating point or integer array between Fortran and Basic, for example.
The length of the string in the Fortran subroutine equals the input length of the string. Any additional characters are ignored in the Fortran subroutine. If the return string is shorter than the length, trailing blanks are appended. The called Fortran subroutine is within the scope of the calling Basic program and cannot alter the memory allocation of a string passed as a dummy argument without tripping a memory access violation in the calling Basic program.

This VB info may not be what you need, but it generalises how strings have been passed between VB and Fortran.


0 Kudos
Reply