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

Reading Character Strings

Mark_Gracey
Beginner
986 Views
I am calling an Intel Fortran DLL from VB6.

A 7-character string is set by the Fortran, and I want to use it in the VB.
However, when I try to declare the Fortran subroutine in the VB, I am not allowed to set the character length, and so the program crahes.
I can set the variable as character*7 in Fortran and string*7 in VB, but only string at the interface.

Does anyone know a way round this?

Thanks,

Mark.
0 Kudos
2 Replies
anthonyrichards
New Contributor III
986 Views
When sending or receiving character strings to and from Fortran, Fortran will expect to receive or send the string length as a 'hidden' value after the address of the string. Just define a second variable in your VB declaration of the sending or receiving routine or function as follows:

Private Declare Sub SendFortranString Lib "c:\f90\FCall\Debug\FCall.dll" (ByVal A1 As String, ByVal L1 As Long)
Private Declare Function GetFortranString Lib "c:\f90\FCall\FCall2\Debug\FCall2.dll" (ByRef A1 As String, ByVal L1 As Long) As Integer

In my example the code I used for the two Fortran DLLs FCALL (which sends a string to Fortran) and FCALL2 (which receives a string from Fortran) is as follows:

FCALL

************************************************************************************
! FCall.f90
!
! FUNCTIONS/SUBROUTINES exported from FCall.dll:
!! SendFortranString - SUBROUTINE
!
! The Visual Basic calling code specifies using the first argument by value (ByVal)
! hence the character string is supplied, whose Value is automatically
! assumed to be provided as the first argument, hence the character type for the first argument.
!
! The length of the character string has been made available by Visual Basic in its calling code
! as a second 'hidden' argument that Fortran expects and uses to set the amount of storage to
! reserve for the character string.
!
! Although Visual Basic stores strings as unicode (2 bytes per character) it automatically
! converts from unicode to Ascii when sending strings to external code
! (as indicated by the Declare statement in the VB code) such as C,C++ and, in the present
! case, Fortran). Hence the supplied string consists of ASCII characters (1 byte per character).
!

SUBROUTINE SENDFORTRANSTRING (MYSTRINGIN)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "SendFortranString" :: SENDFORTRANSTRING
USE DFWIN
USE DFWINTY

IMPLICIT NONE
CHARACTER*(*) MYSTRINGIN
INTEGER LENGTHIN, LOCSTRING
INTEGER LRET

LENGTHIN=LEN_TRIM(MYSTRINGIN)
LOCSTRING=LOC(MYSTRINGIN)
! MESSAGEBOX requires null-terminated text strings....
LRET= MESSAGEBOX(0,"SENDFORTRANSTRING Entered: Supplied string = "//CHAR(13)//CHAR(10)// &
MYSTRINGIN//CHAR(0),"Calling FCall.DLL"//CHAR(0),MB_OK)

RETURN

END SUBROUTINE SENDFORTRANSTRING

************************************************************************************

and FCALL2:

! FCall2.f90
!
! FUNCTIONS/SUBROUTINES exported from FCall2.dll:
! GetFortranString - FUNCTION

! The Visual Basic calling code specifies using the first argument by reference (ByRef)
! hence a pointer to the character string is supplied, whose Value is automatically
! assumed to be provided as the first argument, hence the Integer type for the first argument.
!
! The length of the buffer made available by Visual Basic to take the returned string
! MUST be supplied, so that no more than this number of characters will be copied to the
! memory address pointed to by the first argument, thus removing the risk of buffer over-run.
! This length is explicitly supplied as the second argument, by value, and is not supplied
! as a 'hidden' argument (which would be the case if the first argument was supplied
! by value).
!
! Although Visual Basic stores strings as unicode (2 bytes per character) it automatically
! converts from unicode to Ascii when sending strings to external code
! (as indicated by the Declare statement in the VB code) and when receiveing strings back
! from such external code (such as C,C++ and, in the present case, Fortran)
!
INTEGER FUNCTION GETFORTRANSTRING (PTRSTRING, BUFFLENGTH)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "GetFortranString" :: GETFORTRANSTRING
!DEC$ ATTRIBUTES VALUE:: BUFFLENGTH
USE DFWIN
USE DFWINTY
USE DFWBASE, ONLY: COPYMEMORY

IMPLICIT NONE
INTEGER*4 PTRSTRING, BUFFLENGTH
INTEGER STRLENGTH, PTRSTRINGOUT
! Define a character string buffer of appropriate length for your string
CHARACTER(120) MYSTRINGOUT
CHARACTER*10 CHBUFFLENGTH
INTEGER LRET

! MESSAGEBOX requires null-terminated C-strings....
LRET= MESSAGEBOX(0,"GETFORTRANSTRING ENTERED"C,"CALLING FCALL.DLL"C,MB_OK)

WRITE(CHBUFFLENGTH,'(I10)') BUFFLENGTH
LRET=MESSAGEBOX(0,"Input string BUFFER length = "//chbufflength//char(0), &
"Calling GETFORTRANSTRING in FCall2.DLL"//char(0),MB_OK)
MYSTRINGOUT="Here is my null-terminated RETURNED string AFTER CALL TO FORTRAN"//CHAR(0)
PTRSTRINGOUT=LOC(MYSTRINGOUT)

STRLENGTH=LEN_TRIM(MYSTRINGOUT)
IF(STRLENGTH.LE.BUFFLENGTH) THEN
! Copy MYSTRINGOUT pointed to by PTRSTRINGOUT to buffer pointed to by PTRSTRING
! ensure you do not write beyond end of input buffer
CALL CopyMemory(PTRSTRING, PTRSTRINGOUT,STRLENGTH)
GETFORTRANSTRING=STRLENGTH
ELSE
!If string is longer than the input buffer, do a truncated copy and return
!The length of the string with a minus sign
CALL CopyMemory(PTRSTRING, PTRSTRINGOUT,BUFFLENGTH)
GETFORTRANSTRING=-STRLENGTH
END IF

return

END FUNCTION GETFORTRANSTRING
************************************************************************************

To test the DLLS, just supply a Form that allows entry of a text string into one list box and the display of the sent and received strings in two other list boxes, with buttons to click, one to 'Send' and the other to 'Receive'. See the attached document for screen shots taken during Visual Fortran debug sessions which allowed the memory locations occupied by the strings to be displayed, and which also shows a screenshot of the Visual Basic project used to create a VB .EXE that was executed in order to demonstrate the use of the code in the Fotran Dlls.

Note that VB uses Unicode strings and automatically converts to and from ASCII code when sending or receiving strings from external functions.
0 Kudos
Mark_Gracey
Beginner
986 Views
Thank you.
I'll go off and apply that,
Mark.
0 Kudos
Reply