如何在独立文件中定义的Fortran中调用函数? [英] How to call a function in Fortran that is defined in a separate file?

查看:1083
本文介绍了如何在独立文件中定义的Fortran中调用函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图编译一些真正的旧代码(1986年和之前)。这段代码引用了一个外部函数。今天的编译器要求更多的代码来完成这项工作。我一直在失败。
我现在创建了一个小型的hello世界程序,它演示了这个问题。



hello.for

  PROGRAM hello 
USE func
PRINT *,Hello World!
PRINT *,f()
END PROGRAM你好

func.for

 模块func 
PUBLIC f
包含
函数f()
f =' Hello Func'
END FUNCTION
END MODULE

这不仅有一个,但有两个问题:


  • 如何定义返回类型?文档告诉< type> FUNCTION< function> FUNCTION< function> ()< type> ::< something> ,但都不起作用。 b
    $ b $ p $ gfortran -c func.for 可以工作(如果我使用默认的返回类型real)并创建一个mod文件但链接不起作用

    $ $ p $ $ $ $ $ $ g $ $ $ $ $ $ $ $ / $ / $ / $ / $ / $ / tmp / ccHNzcXA.o:在函数中'MAIN__':
    hello.for :(。text + 0xa4):未定义引用'__func_MOD_f'
    collect2:错误:ld返回1退出状态

    __ func_MOD_f 不是包含在mod文件中,而是在o文件有 func.for__func_MOD_f



    有什么想法?

    感谢

    解决方案

    您有两个问题, f 并正确链接模块。



    首先,编译模块会产生错误:

     %gfortran -c func.f 
    func.f:5:8:

    f = 'Hello Func'
    1
    错误:无法在(1)处将CHARACTER(1)转换为REAL(4)

    这个错误是由于隐式键入 f 和一个不兼容的赋值。解决这个问题很简单,将 f 明确地声明为字符而不是隐式类型。 Add:

     字符(len = 30):: f 

    到函数,现在你的模块编译。这里是修改后的模块:

     模块func 
    PUBLIC f
    包含
    函数f )
    字符(len = 30):: f
    f ='Hello Func'
    END FUNCTION
    END MODULE






    第二个问题是链接。您的命令:

      gfortran hello.for 

    失败,因为您没有指定模块对象。如果您已经编译了模块,您可以指定:

      gfortran hello.for func.o 


    <$ p $

     

    如果你是我的朋友,请点击这里

    gfortran -o hworld func.for hello.for

    单独编译所有内容:

      gfortran -c func.for 
    gfortran -c hello.for
    gfortran - o hworld hello.o func.o

    其中任何一个都会编译并运行:

     %./hworld 
    Hello World!
    Hello Func






    如果您正在更新你的代码,它也值得添加隐式无来避免任何隐式键入和声明显式变量。例如:

     模块func 
    隐式无
    包含
    函数f
    隐式none
    字符(len = 30):: f
    f ='Hello Func'
    结束函数f
    结束模块func

     程序hello 
    使用func
    隐含无
    print *,Hello World!
    print *,f()
    结束程序hello


    I am trying to compile some really old code (1986 and before). This code references an external function. Today's compilers ask for far more code to make this work. And I keep failing. I now created a small hello world program, which demonstrates the problem.

    hello.for

      PROGRAM hello
        USE func        
        PRINT *, "Hello World!"
        PRINT *, f ()    
      END PROGRAM hello
    

    func.for

      MODULE func
        PUBLIC f
      CONTAINS
        FUNCTION f () 
            f='Hello Func'
        END FUNCTION
      END MODULE
    

    This has not only one, but two problems:

    • How do I define the return type? Docs tell <type> FUNCTION <function> or FUNCTION <function> () <type>::<something> , but neither works.
    • How do I make the linker find the function?

    gfortran -c func.for works (if I use the default return type real) and creates a mod file but linking does not work

    $ gfortran  hello.for 
    /tmp/ccHNzcXA.o: In function `MAIN__':
    hello.for:(.text+0xa4): undefined reference to `__func_MOD_f'
    collect2: error: ld returned 1 exit status
    

    __func_MOD_f is not contained in the mod file, but in the o file there is func.for__func_MOD_f.

    Any idea?

    thanks

    解决方案

    You have two issues, the delcaration of f and properly linking the module.

    First, compiling the module yields the error:

    % gfortran -c func.f
    func.f:5:8:
    
           f='Hello Func'
            1
    Error: Can't convert CHARACTER(1) to REAL(4) at (1)
    

    This error is due to implicit typing of f and an incompatible assignment. Fixing this is simple, declare f explicitly as a character instead of an implicit type. Add:

    character(len=30) :: f
    

    to the function and now your module compiles. Here is the modified module:

      MODULE func
      PUBLIC f
      CONTAINS
      FUNCTION f ()
      character(len=30) :: f
      f='Hello Func'
      END FUNCTION
      END MODULE
    


    Your second problem is linking. Your command:

    gfortran  hello.for  
    

    fails because you did not specify the module object. If you already compiled the module you would specify:

    gfortran hello.for func.o
    

    if you were compiling them both at the same time you would do:

    gfortran -o hworld func.for hello.for
    

    if you are compiling everything individually:

    gfortran -c func.for
    gfortran -c hello.for
    gfortran -o hworld hello.o func.o
    

    Any of these will compile and run:

    % ./hworld 
     Hello World!
     Hello Func   
    


    If you are modernizing your code, it would also be worth adding implicit none to avoid any implicit typing and declaring explicit variables for everything. e.g.:

    module func
      implicit none
    contains
    function f 
      implicit none
      character(len=30) :: f
      f='Hello Func'
    end function f
    end module func
    

    and

    program hello
      use func
      implicit none        
      print *, "Hello World!"
      print *, f ()    
    end program hello
    

    这篇关于如何在独立文件中定义的Fortran中调用函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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