Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
808 views
in Technique[技术] by (71.8m points)

fortran - Why is this a function declared inside the module and then used somewhere else in the same module not seen by the linker?

I have a function (in case anyone is interested, it is this function) in a module that looks like this

MODULE MYMODULE

    IMPLICIT NONE
    ! Some random stuff
    CONTAINS

        CHARACTER*255 FUNCTION strtok ( source_string, delimiters )
         [...]
        END FUNCTION strtok

        SUBROUTINE DO_SOMETHING ( )
           CHARACTER(LEN=255) :: strtok
           [...] ! 
        END SUBROUTINE DO_SOMETHING

END MODULE MYMODULE

The strtok function is a version of C's strings tokenizer, and I'll be using this function from the DO_SOMETHING subroutine. I need to define strtok, otherwise gfortran complains about it being not defined. However, if I do, and compile my code and link it to the main program, the linker complains about an undefined reference to strtok_. I have no idea why this is the case, as they are both in the same module and should be visible. Other functions and subroutines in the same module don't have this problem. Is this something to do with the fact that this is a character*-returning function?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In the following, I'll explain using the complete example below (which you can compile and link to try things):

module mymodule
contains
  integer function foo ()
    foo = 1
  end function

  integer function bar ()
    integer :: foo
    bar = foo()
  end function
end module

program test
  use mymodule
  print *, bar()
end

In the code of function bar, the declaration integer :: foo is strictly equivalent to:

integer, external :: foo

Thus, in the code of bar, you are explicitly stating:

"there may already be a symbol of name foo accessible to you, but from now on, when I use it I mean it to be an external function of this name"

So, this is valid code, and the compiler just expect you to provide an external function named foo. Because you don't (the module function isn't external), it fails to link. You can provide an external foo function by adding the following code (not in the module, just at the end of the same file):

integer function foo ()
  foo = 42
end function

If you add this function body, then your code will compile, and the output will be 42 (as the external function is called, not the module function).

Also worth noting, if you comment out integer :: foo line in the code of bar, symbol foo will resolve to the module function, which will then be called whether or not you provide an external function named foo (thus, the output will be 1).

Conclusion: not a compiler bug, but misuse of an old feature of the language (external declarations). To be honest, I think it's better to explicitly mark your external declarations as such, which would at least have highlighted the issue here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...