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

error #8532, code can be compiled with ifort16, but can't with ifort2021.7

Xiazhengyuan
Beginner
1,289 Views

Dear,

 

The below codes can be compiled with ifort16 and run successed.

It reports "error #8532: A character dummy argument with length other than 1 is not interoperable" when I use ifort2021.7 to compile it.

Could you please tell me how to solve this ? There are many codes like this in our project.

subroutine test(option) BIND(C)
USE, INTRINSIC::ISO_C_BINDING

implicit none
character*132 option(16)
integer i

do i=2,16
if(option(i)(1:7).eq.'SOLVER=') then

elseif(option(i)(1:9).eq.'DIRECT=NO') then
endif
enddo
end

 

Best regard

 

 

0 Kudos
1 Solution
jimdempseyatthecove
Honored Contributor III
1,167 Views
subroutine test(optionsIN) BIND(C)
    USE, INTRINSIC::ISO_C_BINDING

    implicit none
    integer, parameter :: OptionLen = 132
    integer, parameter :: nOptions = 16
    character(len=1) :: optionsIN(nOptions*OptionLen)
    character(len=OptionLen) :: options(nOptions)
    integer :: i
    
    options = transfer(optionsIN, options)
    do i=2,16
        if(options(i)(1:7).eq.'SOLVER=') then
            ! do something
        elseif(options(i)(1:9).eq.'DIRECT=NO') then
            ! do other thing
        endif
    enddo
end subroutine test

Jim Dempsey

View solution in original post

12 Replies
JohnNichols
Valued Contributor III
1,272 Views
subroutine test(option) BIND(C)
USE, INTRINSIC::ISO_C_BINDING

implicit none
character*132 option(16)
integer i

do i=2,16
if(option(i)(1:7).eq.'SOLVER=') then

elseif(option(i)(1:9).eq.'DIRECT=NO') then
endif
enddo
end
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,264 Views

Please post the C/C++ code that you intend to use with (call to) this Fortran subroutine?

 

Jim Dempsey

 

0 Kudos
Ron_Green
Moderator
1,246 Views

The error message is correct.  According to the Standard, Interoperability of intrinsic types.

For character type, interoperability requires the length type parameter to be omitted or be specified by a constant expression whose value is 1. 

Older compilers did not check Standard conformance as strongly as our newer compilers.

0 Kudos
FortranFan
Honored Contributor II
1,244 Views

@Xiazhengyuan ,

Re: your question, "Could you please tell me how to solve this ?", it is tough to recommend something for you given your comment, "There are many codes like this in our project."

As things stand with the use of BIND(C), you and your team will be in a real bind (bad pun intended, sorry!) because you have "many codes like this" in project.

If at all possible, I will suggest a refactoring exercise, which is a one-time effort, to properly update the code(s) in conformance with the ISO IEC Fortran standard and then not to have to worry about it again in the future.  Note you can try kluges and bandaids which may take some effort to work but then you risk it causing problems again with a future change in your toolsets such as the Fortran (and C) compilers.

If a standard-conforming approach is of interest which will require to change (i.e., rafactor) your codes, please post here and I can suggest an option.

0 Kudos
Xiazhengyuan
Beginner
1,217 Views

Thank you all for replying, I have to keep using ifort16.

Many thanks.

 

 

Best regard.

0 Kudos
JohnNichols
Valued Contributor III
1,172 Views

From FF:: If at all possible, I will suggest a refactoring exercise, which is a one-time effort, to properly update the code(s) in conformance with the ISO IEC Fortran standard and then not to have to worry about it again in the future. 

 

This is the problem for all programmers, as the language evolves it develops new features and it provides better checks on old features. The change from MS Fortran 3.03 to MS Powerstation broke more of my code than anything, PS used to give error messages that made no sense and this was before the internet and someone who answered your questions quickly. 

Sooner or later you will have to update,  it is just part of life.  

Good luck.  

JMN

 

PPS - no you can use the new compiler, you just need to sacrifice a weekend to fix the old code.   What is a weekend anyway?

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,168 Views
subroutine test(optionsIN) BIND(C)
    USE, INTRINSIC::ISO_C_BINDING

    implicit none
    integer, parameter :: OptionLen = 132
    integer, parameter :: nOptions = 16
    character(len=1) :: optionsIN(nOptions*OptionLen)
    character(len=OptionLen) :: options(nOptions)
    integer :: i
    
    options = transfer(optionsIN, options)
    do i=2,16
        if(options(i)(1:7).eq.'SOLVER=') then
            ! do something
        elseif(options(i)(1:9).eq.'DIRECT=NO') then
            ! do other thing
        endif
    enddo
end subroutine test

Jim Dempsey

FortranFan
Honored Contributor II
1,150 Views

@jimdempseyatthecove , @Xiazhengyuan :

If the code is to be refactored, I strongly suggest avoiding explicit-shape arguments (parameters) as indicated in Jim's code above but instead to go with assumed-size array of CHARACTER type of length 1 and of explicit kind C_CHAR.

One suggestion will be - if at all possible - to modify the "API" of the procedure and to include the processable length of the parameter as an additional parameter.

Here's an "edited" version with a few other suggestions:

  1. Use MODULEs as much as possible and CONTAIN the procedures in them including those with BIND(C) clause,
  2. Be careful with the string lengths and build in appropriate guards against possibly invalid data access e.g., the strlen check in the snippet below.
  3. Avoid copy instructions as much as possible including those with TRANSFER; in the context of Fortran standard interoperability with a C companion processor, employ the intrinsic module facilities with C_F_POINTER, C_LOC, etc. to utilize reference semantics with the passed data

 

module options_m

   use, intrinsic :: iso_c_binding, only : c_char, c_ptr, c_f_pointer, c_loc

   interface
      function strlen( ps ) result(slen) bind(C, name="strlen")
         import :: c_size_t, c_ptr
         type(c_ptr), intent(in), value :: ps
         integer(c_size_t) :: slen
      end function
   end interface

contains

   subroutine test(option) bind(C, name="test")

      ! Argument list
      character(kind=c_char, len=1), intent(in), target :: option(*) !<-- Assuming intent is in only

      ! Local objects
      integer, parameter :: OptionLen = 132
      integer, parameter :: nOptions = 16

      ! Check the length of the input string against the desired length
      if ( strlen(option) < OptionLen*nOptions ) then
         ! do the needful
      end if

      block
         ! Declare and define a Fortran CHARACTER type of the same kind as input but with
         ! desired length and shape
         character(kind=c_char, len=OptionLen), pointer :: foption(:)
         call c_f_pointer( cptr=c_loc(option), fptr=foption, shape = [ nOptions ] )
         integer :: i
         do i = 2, nOptions
            if ( foption(i)(1:7) == c_char_'SOLVER=' ) then
               ! ..
            else if ( foption(i)(1:9) == c_char_'DIRECT=NO' ) then
               ! ..
            end if
         end do
         foption => null()
      end block

      return

   end subroutine test

end module 

 

 

 

 

Xiazhengyuan
Beginner
1,067 Views

@jimdempseyatthecove Thank you very much. Reshaping is a good way for this, but I have no idea if the size of the option array is assumed.

 

Best regard

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,106 Views

FortranFan,

Your solution is better than mine, with one exception. The if( strlen(option) ... potentially will give false results as the 132 byte entries will likely be filled with null terminated strings. Also, it is likely that less than 16 options may be passed, in which at least the 1st missing option will be a null string. Therefore, this test may need to be removed.

 


Xiazhengyuan,

 

Should these options originate with command line arguments (you copied the command line arguments into this 132*16 byte array), then consider using COMMAND_ARGUMENT_COUNT together with GET_COMMAND_ARGUMENT. (examples included in links).

 

Jim Dempsey

 

0 Kudos
JohnNichols
Valued Contributor III
1,092 Views

Xiazhengyuan

This is called a master class.  

Enjoy. 

One of my former students makes memes, often about me.  Here is one sent last night, she complained I am hard to follow in lectures. 

6wyau6.jpg

0 Kudos
FortranFan
Honored Contributor II
1,034 Views

Jim, @Xiazhengyuan ,

Re: Jim's comment, "The if( strlen(option) ... potentially will give false results as the 132 byte entries will likely be filled with null terminated strings. Also, it is likely that less than 16 options may be passed, in which at least the 1st missing option will be a null string. Therefore, this test may need to be removed."

- note, as Jim mentioned, with the 'option' argument, the Fortran processor really works with a "ByteArray" i.e., a contiguous rank-1 array of CHARACTER type of kind C_CHAR (bytes informally).  And if there are elements of C_NULL_CHAR interspersed in this array, the processing is really fraught.

Thus it will be advisable to have some checks on the input data with the 'option' argument.  `strlen` is just a quick such check.  But the program author can replace it with whatever makes more sense in the context of the program whilst keeping the above aspects re: the Fortran processor in mind.

Then it will be up to the caller to do the needful to have a suitable actual argument passed to the procedure.

 

0 Kudos
Reply