вторник, 24 января 2017 г.

GFortran: доступ к Windows API

Сам вызов функций WinAPI делается на Cи (на примере MessageBox):

// Файл: winapi.c
// *** Вызовы функций Windows API ***
#include <windows.h>

int c_messagebox_(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{ 
    return MessageBox(hWnd, lpText, lpCaption, uType); 
}

Названия функций, которые мы затем будем вызывать из Фортран (в примере – c_messagebox_), должны заканчиваться знаком подчеркивания. В Фортране его не будет – это связано с принципами линковки в GCC.

Для доступа к этим функциям из Фортран-программ целесообразно сделать модуль с обертками:

! Файл: windows.f08
! *** Модуль с интерфейсом к некоторым функциям Windows API ***
module Windows
    use iso_c_binding

    implicit none
    integer(kind=C_LONG), parameter, private :: HWND_DESKTOP       = '00000000'X
    integer(kind=C_LONG), parameter, private :: MB_OK              = '00000000'X
    integer(kind=C_LONG), parameter, private :: MB_ICONERROR       = '00000010'X
    integer(kind=C_LONG), parameter, private :: MB_ICONINFORMATION = '00000040'X

    interface
        function c_messagebox(hWnd, lpText, lpCaption, uType)
            use iso_c_binding
            integer(kind=C_LONG)          :: c_messagebox
            integer(kind=C_LONG), value   :: hWnd, uType
            character(kind=C_CHAR, len=*) :: lpText, lpCaption
        endfunction 
    endinterface

contains 

    subroutine MsgErr(str)   ! Выводит простой MessageBox с ошибкой
        character(*)    :: str
        integer         :: res
        res = c_messagebox(HWND_DESKTOP, str // C_NULL_CHAR, &
              "Ошибка" // C_NULL_CHAR, MB_ICONERROR + MB_OK)
    endsubroutine 

    subroutine MsgInf(str)   ! Выводит простой MessageBox c информацией
        character(*)    :: str
        integer         :: res
        res = c_messagebox(HWND_DESKTOP, str // C_NULL_CHAR, &
              "Информация" // C_NULL_CHAR, MB_ICONINFORMATION + MB_OK)
    endsubroutine

endmodule

Здесь вызов функций из модуля на Си осуществляется через interface с указанием специальных разновидностей типов (C_LONG, C_CHAR), определенных для совместимости с Си в модуле iso_c_binding, входящим в GCC.

NB! В процедурах-обертках к строкам приходится добавлять C_NULL_CHAR.

Для проверки:

! Файл: test.f08
program Test
    use Windows
    call MsgInf("Это информация.")
    call MsgErr("А это ошибка!")
endprogram

Компилируем и запускам:

gcc -c winapi.c
gfortran -c windows.f08
gfortran -c test.f08
gfortran *.o -o test.exe
test.exe

Если все хорошо, получаем:


1 комментарий:

  1. Получилось!
    Пришлось заменить '00000000'X '00000010'X '00000040'X на 0 16 64.
    Русский текст перевирает.
    gfortran *.o -o test.exe заменить на gfortran winapi.o windows.o test.o -o test.exe

    ОтветитьУдалить