32 位 Windows gFortran 中的这个链接器错误是一个错误吗?
Is this linker error in 32 bit Windows gFortran a bug?
以下代码编译为 64 位,但使用 Fortran 通用接口似乎混淆了 32 位中的 gcc 属性(需要调用 32 位 STDCALL API)。该代码是 f03gl 项目的精简版本,我正在尝试为 Windows 构建该项目(我无法创建更小的重现)。
没有通用接口和直接传递参数的代码返工(显示在底部)确实可以编译和工作。我希望我不必重写所有调用来解决这个问题。
错误是;
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 的处理。
我在 64 位 Windows 上使用 msys2(GNU Fortran(Rev2,由 MSYS2 项目构建)7.1.0)下的 gfortran 以及 32 位和 64 位编译器。
将 STDCALL 属性应用于仅是通用名称的标识符没有意义。从编译器的角度来看,通用名称是许多过程的通用标签。虽然各个特定过程可能有不同的调用约定,但它们的标签却没有。
如果要告诉编译器某个特定过程具有特定的调用约定,请在相关声明中使用编译器知道该特定过程的名称。
!GCC$ ATTRIBUTES stdcall :: glutInit_gl
以下代码编译为 64 位,但使用 Fortran 通用接口似乎混淆了 32 位中的 gcc 属性(需要调用 32 位 STDCALL API)。该代码是 f03gl 项目的精简版本,我正在尝试为 Windows 构建该项目(我无法创建更小的重现)。
没有通用接口和直接传递参数的代码返工(显示在底部)确实可以编译和工作。我希望我不必重写所有调用来解决这个问题。
错误是;
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 的处理。
我在 64 位 Windows 上使用 msys2(GNU Fortran(Rev2,由 MSYS2 项目构建)7.1.0)下的 gfortran 以及 32 位和 64 位编译器。
将 STDCALL 属性应用于仅是通用名称的标识符没有意义。从编译器的角度来看,通用名称是许多过程的通用标签。虽然各个特定过程可能有不同的调用约定,但它们的标签却没有。
如果要告诉编译器某个特定过程具有特定的调用约定,请在相关声明中使用编译器知道该特定过程的名称。
!GCC$ ATTRIBUTES stdcall :: glutInit_gl