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

/iface:nomixed_str_len_arg

tkibedi
Beginner
1,243 Views
Building an application, which is using a third party library, I have the following problem. The subroutine in that library requires to use the /iface:nomixed_str_len_arg compiler option to pass the string arguments. Here is the subroutine, which calls the third party library routine, INTERP:
Subroutine MySub(SolutionFile, Xvalue, Yvalue, Xcomponent,Ycomponent)
CHARACTER (LEN=256) :: SolutionFile
REAL (KIND=8) :: Xvalue,Yvalue
REAL (KIND=8) :: Solution,Xcomponent,Ycomponent
REAL (KIND=8) :: DBYDY,DBYDX,DBXDY
Integer (KIND=4) :: Iostat1
! -----------------------------------------------------------------------------
Interface
Integer*4 function INTERP(SolutionFile,Xvalue,Yvalue, &
Solution,Xcomponent,Ycomponent,DBYDY,DBYDX,DBXDY);
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS : '_INTERP@36' :: INTERP
CHARACTER(LEN=256),INTENT(IN) :: SolutionFile
!DEC$ ATTRIBUTES REFERENCE :: SolutionFile
REAL (KIND=8),INTENT(IN) :: Xvalue,Yvalue
REAL (KIND=8),INTENT(OUT) :: Solution,Xcomponent,Ycomponent
REAL (KIND=8),INTENT(OUT) :: DBYDY,DBYDX,DBXDY
End Function INTERP
End Interface
Iostat1 = INTERP(SolutionFile, &
Xvalue, Yvalue, &
Solution, Xcomponent, Ycomponent, &
DBYDY, DBYDX, DBXDY)
....
The program is linked with a number of libraries, which has been created with default settings.
I tried to compile the MySub routine with the/iface:nomixed_str_len_arg option andthe rest of the project with the default one.
The linker gives an "unresolved external symbol _MySub@28" error. Could somebody give some help, how to resolve this problem.
0 Kudos
8 Replies
ipattielgc
Beginner
1,243 Views

Ok, couple of things to look at:

1) @28 means 28/4=7 arguments, so one char, plus hidden counts as 2, meaining MySub is called somewhere with 6 arguments, I only see 5 in the definition, which would compile as @24, if....

2) The sub decoration @28 is not related to the mixed_str_len directive, but rather depends on the calling convention. I.e., "cvf" would do this, but some others would not.

-Ian

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,243 Views
The subroutine in that library requires to use the /iface:nomixed_str_len_arg compiler option to pass the string arguments.
Integer*4 function INTERP(SolutionFile,Xvalue,Yvalue, &
Solution,Xcomponent,Ycomponent,DBYDY,DBYDX,DBXDY);
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS :
'_INTERP@36' :: INTERP
CHARACTER(LEN=256),INTENT(IN) :: SolutionFile
!DEC$ ATTRIBUTES REFERENCE :: SolutionFile
I fail to see relavance of /iface:nomixed_str_len_arg here.Yousaythe library in question, containing INTERP, is built with that option. However, your INTERFACE block specifies REFERENCE for SolutionFile argument, and that means that string lengh is NOT passed at all. Name mangling (@36) is consistent with the rest of the interface. So, /iface:nomixed_str_len_arg does nothing -- at least regarding INTERP -- unless there are some other routines you didn't show.
I tried to compile the MySub routine with the/iface:nomixed_str_len_arg option andthe rest of the project with the default one.
Now, that's a no-no. MySub will expect the len(SolutionFile) on the last position on the stack, but the rest of the code will put it on the 2nd. That can screw the things very badly. Either build everything with /iface:no... or nothing. If you have mixed-case, youcan provide INTERFACE block with !DEC$ATTRIBUTES NOMIXED_STR_LEN_ARG (but note that it'snullifiedif you specify REFERENCE as I said above). I suggest to be consistent accross your own code, and provide INTERFACEs for external stuff.
The linker gives an "unresolved external symbol _MySub@28"
Um, "_MySub"? Not "_MYSUB"? Strange. (I wouldn't expect a linker error, but rather a run-time crash).
Jugoslav
0 Kudos
tiborkibedi
Beginner
1,243 Views

Dear Jugoslav,

Thanks for your help. Changing the interface declaration to:

Interface
! -----------------------------------------------------------------------------
Integer*4 function INTERP(SolutionFile,Xvalue,Yvalue, &
Solution,Xcomponent,Ycomponent,DBYDY,DBYDX,DBXDY);
!DEC$ ATTRIBUTES NOMIXED_STR_LEN_ARG, DLLIMPORT, ALIAS : '_INTERP@36' :: INTERP
CHARACTER(LEN=256),INTENT(IN) :: SolutionFile
!DEC$ ATTRIBUTES NOMIXED_STR_LEN_ARG :: SolutionFile
REAL (KIND=8),INTENT(IN) :: Xvalue,Yvalue
REAL (KIND=8),INTENT(OUT) :: Solution,Xcomponent,Ycomponent
REAL (KIND=8),INTENT(OUT) :: DBYDY,DBYDX,DBXDY
End Function INTERP
End Interface

works well with the project compiled with default settings.

Tibor

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,243 Views
Hmmm. It's odd. You have ALIAS ...@36, which means 9 entries on the stack. On the other hand,there are9 arguments in the list, one being string, which means 10 stack entries in total, which means that the alias should be ...@40. Thus, it shouldn't have worked.
That means that either
- the INTERFACE is correct, but a "smart" guy explicitly ALIASed INTERP to _INTERP@36 at dllexport in order to confuse us all.
- there's something else fishy going on.
I'd suggest that you test the stack pointer before and after the call in the debuggerusing method with ExCheckStack described here. If the sanity check fails, that means you have just hidden the symptoms rather than cure them.
Jugoslav
0 Kudos
ipattielgc
Beginner
1,243 Views

No doubt its working because of the bug in ifort .47 which incorrectly decorates the function name when characters arguments are present, in some cases.

Premier support (thanks!)has told me this bug will be fixed in the next compiler release, which may cause this code to break... Ian.

0 Kudos
tkibedi
Beginner
1,243 Views

I tried what Jugoslav suggested and it appears the code is working as it is.

Thanks Ian to point out the bug in ifort. I am using CVF 6.6c. Interestingly, changing the interface to _INTERP@40gives a linker error.

Tibor

0 Kudos
tkibedi
Beginner
1,243 Views

Unfortunately, there was a type in the last Interface I posted. The attributes of the SolutionFile was incorrect. The correctbit of codereads:

Interface
! -----------------------------------------------------------------------------
Integer*4 function INTERP(SolutionFile,Xvalue,Yvalue, &
Solution,Xcomponent,Ycomponent,DBYDY,DBYDX,DBXDY);
!DEC$ ATTRIBUTES NOMIXED_STR_LEN_ARG, DLLIMPORT, ALIAS : '_INTERP@36' :: INTERP
CHARACTER(LEN=256),INTENT(IN) :: SolutionFile
!DEC$ ATTRIBUTES REFERENCE :: SolutionFile
REAL (KIND=8),INTENT(IN) :: Xvalue,Yvalue
REAL (KIND=8),INTENT(OUT) :: Solution,Xcomponent,Ycomponent
REAL (KIND=8),INTENT(OUT) :: DBYDY,DBYDX,DBXDY
End Function INTERP
End Interface

Tibor
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,243 Views

That makes more sense.

However, note that !DEC$ATTRIBUTES NOMIXED_STR_LEN_ARG issuperfluous in this case. By default, (/iface:mixed_strlen_arg), string length is passed immediately behind the string argument; with (/iface:nomixed_strlen_arg), it is passed at the end of arg-list. However, if you explicitly specify !DEC$ATTRIBUTES REFERENCE for a string argument, then the string length is not passed at all. (And the callee must deduce it by other means). Footprint @36 proves that it is the case -- 9 arguments matching 9 stack entries. i.e. no hidden length.

Jugoslav

0 Kudos
Reply