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

Perenial string problem: IVF/VC++6

bendel_boy
Beginner
369 Views
Tring to swap a string between Fortran & C++. The string gets pased oK, and a result returned, but the call cleanup seems to have a problem, leading ultimately to an access violation.

C++ code is

extern "C" __declspec(dllimport)long GetIndex(char * Code, unsigned long LenCode);
Len = 7;
CATION = GetIndex("CATION", Len);
CATION = CATION - 1; // Fortran 1-index; C 0-index

When I step through the code the problems arise after the return from GetIndex & during the assignment to CATION.

Fortran code is
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE:: GetIndex
!DEC$ ATTRIBUTES ALIAS: '_GetIndex':: GetIndex
integer function GetIndex(Code)
USE StreamMatch
USE PrivateStreamData

character:: Code*(*)

integer:: i, result
character*ID_LEN:: test
result = 0
test = lower(Code)
i = len_trim(test)
if (test(i:i) .eq. CHAR0) i = i - 1
do j = 1, iNumberOfDeterminands
if (test(1:i) .eq. Names(j)(1:len_trim(Names(j)))) then
result = j
exit
end if
end do
GetIndex = result
end function
0 Kudos
2 Replies
Lorri_M_Intel
Employee
369 Views

In the C code, you're defining the external routine to have "C" calling standard.

In the Fortran code, you're defining the external routine to have STDCALL calling standard.

You're correct in your statement that these don't match. smiley [:-)]

Make them match - either set the C routine to be __stdcall or set the Fortran routine to be C. I did not confirm this by creating a main program to callyoursubroutine but you may be able to simply remove the STDCALL attribute from the Fortran declaration.

- Lorri

0 Kudos
anthonyrichards
New Contributor III
369 Views
If I may be allowed to blow my own trumpet, see this recent thread:
http://software.intel.com/en-us/forums//topic/58864
The attachment given there supplies C-code and Fortran code that agree and allow back and 
forth transfer of character strings. I always pass arguments by reference from
C to Fortran and I find it avoids most problems. I recommend you do the same
and mark the arguments as by REFERENCE in the Fortran.(I always include the string
length as an argument also).
So on the C++ side I would pass pointers to the string and its length as arguments 
extern
"C" { __declspec(dllimport) void __stdcall FORTDISPLAYMESSAGE(char *lpszstring, int &strlength); }
and, on the Fortran side, accept addresses as follows:
subroutine FORTDISPLAYMESSAGE(lpszstring, strlength)
! Expose subroutine strings to users of this DLL
!
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_FORTDISPLAYMESSAGE@8' :: FORTDISPLAYMESSAGE
!DEC$ ATTRIBUTES DLLEXPORT::FORTDISPLAYMESSAGE
!DEC$ ATTRIBUTES REFERENCE:: lpszstring, strlength
! Variables
INTEGER STRLENGTH
character(STRLENGTH) lpszstring
I believe __stdcall causes the addition of the @8 to the function name, the 
leading underscore also being added, hence the need for the ALIAS as shown.
0 Kudos
Reply