суббота, 11 марта 2017 г.

GFortran: конвертируем библиотеки .a в DLL

Бывает, что у нас имеются библиотеки .a только для статической линковки, а мы бы хотели вместо них иметь DLL и подключать ее динамически.

Примером может быть библиотека линейной алгебры LAIPE2 с стайта www.equation.com.

Оказывается, из .a очень просто сделать DLL автоматически.

Нам потребуется файл-заглушка Dllmain.f90 с пустой процедурой:

subroutine my_dll_main()
endsubroutine 

Откомпилируем его в DLL с подключением соответствующих библиотек (в данном примере – liblaipe2.a и нужная ей для работы libneuloop4.a):

gfortran dllmain.f90  -shared -o laipe2.dll -Wl,-export-all-symbols 
-Wl,-enable-auto-import -Wl,-no-undefined -Wl,--enable-runtime-pseudo-reloc 
-Wl,-whole-archive liblaipe2.a libneuloop4.a -Wl,-no-whole-archive

Тут довольно много ключей для линковщика – я их взял из примера, найденного в интернете, в смысл особо не погружался. Главное, что это работает.

Протестировать полученную DLL можно дополнив пример из прошлого поста:

! Вставка в файл LapackFromDll.F90:
...
    !> Интерфейсы функций LAIPE2
    abstract interface
        subroutine laipe_use_(N)
            integer  N
        endsubroutine
        subroutine laipe_done_()
        endsubroutine
        subroutine laipe_DAG_8_(A_io, N_i, X_io, NoGood_o)
            integer           NoGood_o, N_i
            double precision  A_io(*), X_io(*) 
        endsubroutine
    endinterface
    !> Процедуры-указатели на функции LAIPE2
    procedure(laipe_use_)  , pointer  :: laipe_use
    procedure(laipe_done_) , pointer  :: laipe_done
    procedure(laipe_DAG_8_), pointer  :: laipe_DAG_8
...
! Вставка в файл LinTest.F90:
...
    call LoadDll(LinAlg_dll, "laipe2.dll")
    call DllProcAssoc(LinAlg_dll, laipe_use,   "laipe$use_")
    call DllProcAssoc(LinAlg_dll, laipe_done,  "laipe$done_")
    call DllProcAssoc(LinAlg_dll, laipe_DAG_8, "laipe$solution_dag_8_")
    call laipe_use(8)
    A = A0 ; X = B 
    call laipe_DAG_8(A, n, X, info)
    print "(' *** Решение с помощью laipe2.dll (info = ',i1,'):')", info
    print FRM, X
    call laipe_done()
    call FreeDll(LinAlg_dll) 
...

Комментариев нет:

Отправить комментарий