2017-08-20 1 views
1

Le code suivant est compilé en 64 bits mais l'utilisation des interfaces génériques Fortran semble confondre l'attribut gcc en 32 bits (requis pour appeler l'API STDCALL 32 bits). Le code est une version allégée du projet f03gl que je tente de construire pour Windows (je ne pouvais pas créer un repro plus petit).Est-ce que cette erreur de l'éditeur de liens dans Windows 32 bits gFortran un bug?

Un remaniement du code (affiché en bas) sans l'interface générique et le passage direct des arguments compile et fonctionne. J'espère que je n'aurai pas à réécrire tous les appels pour contourner ce problème.

L'erreur est;

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

callglut.f90 (compilation échoue 32 bits)

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 

L'interface générique est utilisée pour appeler glutInit sans paramètres de Fortran (les paramètres sont renseignés par le sous-programme proxy).

callglut.f90 (compile et fonctionne sur les plates-formes)

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 

que je vois un bug du compilateur avec l'instruction attribut ne pas être appliqué à une interface générique ou est-ce que je fais ? Je pense que ceci et le changement de nom STDCALL 32 bits de glutInit à _glutInit @ 8 n'est pas effectué. J'utilise gfortran sous msys2 (GNU Fortran (Rev2, Construit par le projet MSYS2) 7.1.0) sur Windows 64 bits avec les deux compilateurs 32 et 64 bits.

Répondre

1

Cela n'a aucun sens d'appliquer l'attribut STDCALL à un identificateur qui est seulement un nom générique. Du point de vue du compilateur, un nom générique est une étiquette commune pour un certain nombre de procédures. Alors que les procédures spécifiques individuelles peuvent avoir différentes conventions d'appel, l'étiquette pour eux ne le fait pas.

Si vous voulez dire au compilateur qu'une procédure spécifique a une certaine convention d'appel, utilisez le nom que le compilateur connaît la procédure spécifique, dans la déclaration correspondante.

!GCC$ ATTRIBUTES stdcall :: glutInit_gl 
+0

Merci, je me suis cogné la tête contre un mur à ce sujet. J'ai supposé que le nom après :: était pour le nom exporté de la bibliothèque, pas le nom local. Assez confus. Avez-vous de bonnes références à ce sujet, car je trouve encore confus? –

+0

Je ne suis pas sûr de ce que vous entendez par "nom exporté de bibliothèque". Les directives du compilateur de gfortran sont documentées sur https://gcc.gnu.org/onlinedocs/gfortran/GNU-Fortran-Compiler-Directives.html – IanH