【问题标题】:Is this linker error in 32 bit Windows gFortran a bug?32 位 Windows gFortran 中的这个链接器错误是一个错误吗?
【发布时间】:2017-08-20 14:34:53
【问题描述】:

以下代码编译为 64 位,但使用 Fortran 通用接口似乎会混淆 32 位中的 gcc 属性(调用 32 位 STDCALL API 所需的)。该代码是我正在尝试为 Windows 构建的 f03gl 项目的精简版本(我无法创建更小的复制品)。

没有通用接口和直接传递参数的代码(显示在底部)的返工确实可以编译和工作。我希望我不必重写所有调用来解决这个问题。

错误是;

callglutbad.o:callglutbad.f90:(.text+0x27): undefined reference to `glutInit'

callglut.f90(32 位编译失败)

MODULE GlutModule
  USE ISO_C_BINDING
  IMPLICIT NONE
  PUBLIC glutInit

  INTERFACE glutInit
    MODULE PROCEDURE glutInit_f03
  END INTERFACE glutInit

  INTERFACE

    SUBROUTINE glutInit_gl(pargc, argv) BIND(C,NAME="glutInit")
      IMPORT

#ifdef x86
!GCC$ ATTRIBUTES stdcall :: glutInit
#endif
      INTEGER(C_INT) :: pargc
      TYPE(C_PTR), INTENT(IN) :: argv
    END SUBROUTINE glutInit_gl

  END INTERFACE

  CONTAINS

  SUBROUTINE glutInit_f03()
    INTEGER(C_INT) :: argcp=1
    TYPE(C_PTR), DIMENSION(1), TARGET :: argv=C_NULL_PTR
    CHARACTER(C_CHAR), DIMENSION(1), TARGET :: empty_string=C_NULL_CHAR

    argv(1)=C_LOC(empty_string)
    CALL glutInit_gl(argcp, C_LOC(argv))

  END SUBROUTINE

END MODULE GlutModule

program main
  USE GlutModule

  PRINT *,"Calling glutInit"
  call glutInit()
  PRINT *,"Called glutInit"

end program main

build.bat

REM 32 bit 
@setlocal
@SET PATH=%PATH%;C:\msys64\mingw32\bin\
gfortran -Dx86 -cpp -c callglut.f90 -o callglut.o
gcc callglut.o -o callglut32.exe ..\x86\lib\freeglut.lib -lgfortran
@endlocal

REM 64 bit 
@setlocal
@SET PATH=%PATH%;C:\msys64\mingw64\bin\
gfortran -cpp -c callglut.f90 -o callglut.o
gcc callglut.o -o callglut64.exe ..\x64\lib\freeglut.lib -lgfortran
@endlocal

通用接口用于从Fortran调用不带参数的glutInit(参数由代理子程序填写)。

callglut.f90(在两个平台上编译和运行)

MODULE GlutModule
  USE ISO_C_BINDING
  IMPLICIT NONE
  PUBLIC glutInit

  INTERFACE

    SUBROUTINE glutInit(pargc, argv) BIND(C,NAME="glutInit")
      IMPORT

#ifdef x86
!GCC$ ATTRIBUTES stdcall :: glutInit
#endif
      INTEGER(C_INT) :: pargc
      TYPE(C_PTR), INTENT(IN) :: argv
    END SUBROUTINE glutInit
  END INTERFACE

END MODULE GlutModule

program main
  USE GlutModule

  PRINT *,"Calling glutInit"
  call glutInit(0,C_NULL_PTR)
  PRINT *,"Called glutInit"

end program main

我是否看到了一个编译器错误,其中属性语句未应用于通用接口,还是我正在做的事情?我怀疑这和 32 位 STDCALL 名称从 glutInit 到 _glutInit @8 没有被执行。

我在带有 32 位和 64 位编译器的 64 位 Windows 上的 msys2(GNU Fortran(Rev2,由 MSYS2 项目构建)7.1.0)下使用 gfortran。

【问题讨论】:

    标签: fortran gfortran


    【解决方案1】:

    将 STDCALL 属性应用于仅是通用名称的标识符是没有意义的。从编译器的角度来看,通用名称是许多过程的通用标签。虽然各个特定过程可能有不同的调用约定,但它们的标签却没有。

    如果您想告诉编译器某个特定过程具有某种调用约定,请在相关声明中使用编译器知道该特定过程的名称。

    !GCC$ ATTRIBUTES stdcall :: glutInit_gl
    

    【讨论】:

    • 谢谢,我一直在用头撞墙。我假设 :: 之后的名称是库导出名称,而不是本地名称。相当混乱。您对此有什么好的参考资料,因为我仍然觉得它令人困惑?
    • 我不确定您所说的“库导出名称”是什么意思。 gfortran 的编译器指令记录在 gcc.gnu.org/onlinedocs/gfortran/…
    猜你喜欢
    • 2011-03-09
    • 2011-12-31
    • 2015-11-26
    • 1970-01-01
    • 2012-09-18
    • 2012-03-25
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多