为什么这是一个在模块内声明的函数,然后在链接器看不到的同一模块中的其他地方使用? [英] Why is this a function declared inside the module and then used somewhere else in the same module not seen by the linker?

查看:8
本文介绍了为什么这是一个在模块内声明的函数,然后在链接器看不到的同一模块中的其他地方使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数(如果有人感兴趣,它是 这个函数)看起来像这样的模块

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

strtok 函数是 C 字符串标记器的一个版本,我将在 DO_SOMETHING 子例程中使用这个函数.我需要定义 strtok,否则 gfortran 会抱怨它没有被定义.但是,如果我这样做,并编译我的代码并将其链接到主程序,链接器会抱怨对 strtok_ 的未定义引用.我不知道为什么会这样,因为它们都在同一个模块中并且应该是可见的.同一模块中的其他函数和子程序没有这个问题.这与这是一个字符*返回函数有关吗?

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?

推荐答案

下面,我将使用下面的完整示例进行解释(您可以编译并链接以进行尝试):

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

在函数bar的代码中,声明integer :: foo严格等价于:

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

integer, external :: foo

因此,在 bar 的代码中,您明确说明:

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

"可能已经有名字的符号foo 可供您访问,但从现在开始on,当我使用它时,我的意思是它是一个此名称的外部函数"

"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"

所以,这是有效的代码,编译器只是希望您提供一个名为 fooexternal 函数.因为你没有(模块函数不是外部的),所以它无法链接.您可以通过添加以下代码来提供外部 foo 函数(不在模块中,只是在同一文件的末尾):

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

如果你添加这个函数体,那么你的代码将被编译,输出将是42(因为调用的是外部函数,而不是模块函数).

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).

另外值得注意的是,如果在bar的代码中注释掉integer :: foo这一行,符号foo会解析为模块函数,然后无论您是否提供名为 foo 的外部函数,都会调用该函数(因此,输出将为 1).

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).

结论:不是编译器错误,而是滥用该语言的旧功能(外部声明).老实说,我认为最好明确标记您的 external 声明,这样至少可以突出此处的问题.

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.

这篇关于为什么这是一个在模块内声明的函数,然后在链接器看不到的同一模块中的其他地方使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆