Как сгенерировать DLL, содержащую смешанный код C и Fortran из командной строки, используя Visual Studio и MinGW GFortran? - PullRequest
0 голосов
/ 10 июля 2020

У меня есть программа, использующая C и код Fortran, который я успешно скомпилировал с помощью G CC и GFortran. Я хочу попробовать скомпилировать эту DLL на Windows с помощью Visual Studio и MinGW GFortran, потому что я загружаю эту DLL в программное обеспечение, которое использует компилятор Visual Studio C, и у меня возникли проблемы с использованием DLL, скомпилированной с MinGW G CC. Я также хочу научиться делать это из командной строки, чтобы я мог просто написать пакетный сценарий, который компилирует код в DLL.

Чтобы узнать, как это сделать, я сначала начну с очень простых C и код на Фортране. У меня есть один файл C, test C. C, со следующим кодом:

void fortfunc_(int *ii, float *ff);

int main()
{
    int ii=5;
    float ff=5.5;
    
    fortfunc_(&ii, &ff);
    
    return 0;
}

и один файл Fortran, testF.f, с кодом, показанным ниже.

    subroutine fortfunc(ii,ff)
    integer ii
    real*4 ff

    write(6,100) ii,ff 
100 format('ii=',i2,' ff=',f6.3)

    return
    end

Это очень простая программа, которая будет печатать ii= 5 ff= 5.500 при правильной компиляции и запуске. Я протестировал это с помощью G CC и GFortran, и он работает.

Для простоты я сначала пытаюсь скомпилировать код в exe, а не в DLL. При использовании Visual Studio и MinGW GFortran я запускаю команды, показанные ниже, из командной строки собственных инструментов x64 для VS 2019.

gfortran -c testF.f
cl -c testC.c
cl testC.obj testF.o libgfortran.a /link /out:test.exe 

При запуске я получаю показанную ниже ошибку, включая 31 неразрешенный внешний объект.

LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(open.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(alloc.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(posix.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(lt2-read.o)'
LINK : warning LNK4217: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(transfer.o)' in function '_gfortrani_next_record'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(error.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(memory.o)'
LINK : warning LNK4217: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(unix.o)' in function '_gfortrani_open_external'
LINK : warning LNK4217: symbol '_get_osfhandle' defined in 'libucrt.lib(osfinfo.obj)' is imported by 'libgfortran.a(unix.o)' in function 'raw_truncate'
LINK : warning LNK4217: symbol '__acrt_iob_func' defined in 'libucrt.lib(_file.obj)' is imported by 'libgfortran.a(unix.o)' in function '_gfortrani_flush_if_preconnected'
LINK : warning LNK4217: symbol 'toupper' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(format.o)' in function 'next_char'
LINK : warning LNK4286: symbol 'toupper' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(write.o)'
LINK : warning LNK4217: symbol 'isalnum' defined in 'libucrt.lib(_ctype.obj)' is imported by 'libgfortran.a(read.o)' in function '_gfortrani_read_f'
LINK : warning LNK4217: symbol 'tolower' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(read.o)' in function '_gfortrani_read_f'
LINK : warning LNK4286: symbol 'tolower' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(list_read.o)'
LINK : warning LNK4217: symbol '_strnicmp' defined in 'libucrt.lib(strnicmp.obj)' is imported by 'libgfortran.a(environ.o)' in function 'match_word'
LINK : warning LNK4286: symbol '_strnicmp' defined in 'libucrt.lib(strnicmp.obj)' is imported by 'libgfortran.a(string.o)'
libgfortran.a(transfer.o) : error LNK2019: unresolved external symbol ___chkstk_ms referenced in function skip_record
libgfortran.a(open.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(list_read.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(transfer.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(unix.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(format.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(write.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(transfer.o) : error LNK2019: unresolved external symbol pthread_mutex_lock referenced in function data_transfer_init
libgfortran.a(unix.o) : error LNK2001: unresolved external symbol pthread_mutex_lock
libgfortran.a(unit.o) : error LNK2001: unresolved external symbol pthread_mutex_lock
libgfortran.a(transfer.o) : error LNK2019: unresolved external symbol pthread_mutex_unlock referenced in function data_transfer_init
libgfortran.a(unix.o) : error LNK2001: unresolved external symbol pthread_mutex_unlock
libgfortran.a(unit.o) : error LNK2001: unresolved external symbol pthread_mutex_unlock
libgfortran.a(error.o) : error LNK2019: unresolved external symbol __mingw_vsnprintf referenced in function _gfortrani_st_vprintf
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol __imp__fstat64 referenced in function fd_to_stream
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol __imp__stat64 referenced in function _gfortrani_inquire_formatted.part.14
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol mkstemp referenced in function tempfile_open
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol lseek64 referenced in function raw_seek
libgfortran.a(lt2-read.o) : error LNK2001: unresolved external symbol lseek64
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol pthread_mutex_trylock referenced in function flush_all_units_1
libgfortran.a(unit.o) : error LNK2001: unresolved external symbol pthread_mutex_trylock
libgfortran.a(unit.o) : error LNK2019: unresolved external symbol pthread_mutex_init referenced in function insert_unit
libgfortran.a(unit.o) : error LNK2019: unresolved external symbol pthread_mutex_destroy referenced in function get_gfc_unit
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __udivti3 referenced in function _gfortrani_read_decimal
libgfortran.a(string.o) : error LNK2001: unresolved external symbol __udivti3
libgfortran.a(list_read.o) : error LNK2001: unresolved external symbol __udivti3
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __strtof referenced in function _gfortrani_convert_real
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __strtod referenced in function _gfortrani_convert_real
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __strtold referenced in function _gfortrani_convert_real
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __unordtf2 referenced in function get_precision
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __gttf2 referenced in function get_precision
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __multf3 referenced in function get_precision
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __divtf3 referenced in function get_precision
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __lttf2 referenced in function get_precision
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __subtf3 referenced in function get_precision
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __eqtf2 referenced in function get_float_string
libgfortran.a(write.o) : error LNK2019: unresolved external symbol __letf2 referenced in function get_float_string
libgfortran.a(write.o) : error LNK2019: unresolved external symbol quadmath_snprintf referenced in function get_precision
libgfortran.a(string.o) : error LNK2019: unresolved external symbol __umodti3 referenced in function _gfortrani_gfc_itoa
libgfortran.a(string.o) : error LNK2001: unresolved external symbol __modti3
libgfortran.a(string.o) : error LNK2001: unresolved external symbol __divti3
libgfortran.a(simple.o) : error LNK2019: unresolved external symbol _Unwind_GetIPInfo referenced in function simple_unwind
libgfortran.a(lt1-backtrace.o) : error LNK2001: unresolved external symbol _Unwind_GetIPInfo
libgfortran.a(simple.o) : error LNK2019: unresolved external symbol _Unwind_Backtrace referenced in function backtrace_simple
libgfortran.a(lt1-backtrace.o) : error LNK2001: unresolved external symbol _Unwind_Backtrace
libgfortran.a(fileline.o) : error LNK2019: unresolved external symbol __ms_vsnprintf referenced in function snprintf.constprop.0
libgfortran.a(dwarf.o) : error LNK2001: unresolved external symbol __ms_vsnprintf
test.exe : fatal error LNK1120: 31 unresolved externals

При использовании G CC мне просто нужно было связать библиотеку GFortran, используя -lgfortran. Получив 31 неразрешенный внешний объект при использовании Visual Studio, я решил дополнительно связать libgcc.a libgcc_s.a libpthread.a libquadmath.a. В настоящее время я просто скопировал эти библиотеки из моей установки MinGW в свой рабочий каталог, что, я уверен, не лучший способ сделать это. При связывании этих библиотек количество неразрешенных внешних элементов уменьшается до 10.

LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libquadmath.a(printf_fp.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(open.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(alloc.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(posix.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(lt2-read.o)'
LINK : warning LNK4217: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(transfer.o)' in function '_gfortrani_next_record'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(error.o)'
LINK : warning LNK4286: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(memory.o)'
LINK : warning LNK4217: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'libgfortran.a(unix.o)' in function '_gfortrani_open_external'
LINK : warning LNK4217: symbol '_get_osfhandle' defined in 'libucrt.lib(osfinfo.obj)' is imported by 'libgfortran.a(unix.o)' in function 'raw_truncate'
LINK : warning LNK4217: symbol '__acrt_iob_func' defined in 'libucrt.lib(_file.obj)' is imported by 'libgfortran.a(unix.o)' in function '_gfortrani_flush_if_preconnected'
LINK : warning LNK4217: symbol 'toupper' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(format.o)' in function 'next_char'
LINK : warning LNK4286: symbol 'toupper' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(write.o)'
LINK : warning LNK4217: symbol 'isalnum' defined in 'libucrt.lib(_ctype.obj)' is imported by 'libgfortran.a(read.o)' in function '_gfortrani_read_f'
LINK : warning LNK4217: symbol 'tolower' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(read.o)' in function '_gfortrani_read_f'
LINK : warning LNK4286: symbol 'tolower' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libgfortran.a(list_read.o)'
LINK : warning LNK4286: symbol 'tolower' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libquadmath.a(printf_fphex.o)'
LINK : warning LNK4286: symbol 'tolower' defined in 'libucrt.lib(tolower_toupper.obj)' is imported by 'libquadmath.a(printf_fp.o)'
LINK : warning LNK4217: symbol '_strnicmp' defined in 'libucrt.lib(strnicmp.obj)' is imported by 'libgfortran.a(environ.o)' in function 'match_word'
LINK : warning LNK4286: symbol '_strnicmp' defined in 'libucrt.lib(strnicmp.obj)' is imported by 'libgfortran.a(string.o)'
LINK : warning LNK4217: symbol 'localeconv' defined in 'libucrt.lib(localeconv.obj)' is imported by 'libquadmath.a(printf_fphex.o)' in function '__quadmath_printf_fphex'
LINK : warning LNK4286: symbol 'localeconv' defined in 'libucrt.lib(localeconv.obj)' is imported by 'libquadmath.a(printf_fp.o)'
LINK : warning LNK4217: symbol 'isupper' defined in 'libucrt.lib(_ctype.obj)' is imported by 'libquadmath.a(printf_fphex.o)' in function '__quadmath_printf_fphex'
LINK : warning LNK4286: symbol 'isupper' defined in 'libucrt.lib(_ctype.obj)' is imported by 'libquadmath.a(printf_fp.o)'
libgfortran.a(open.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(list_read.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(transfer.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(unix.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(format.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(write.o) : error LNK2001: unresolved external symbol __mingw_snprintf
libgfortran.a(error.o) : error LNK2019: unresolved external symbol __mingw_vsnprintf referenced in function _gfortrani_st_vprintf
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol __imp__fstat64 referenced in function fd_to_stream
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol __imp__stat64 referenced in function _gfortrani_inquire_formatted.part.14
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol mkstemp referenced in function tempfile_open
libgfortran.a(unix.o) : error LNK2019: unresolved external symbol lseek64 referenced in function raw_seek
libgfortran.a(lt2-read.o) : error LNK2001: unresolved external symbol lseek64
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __strtof referenced in function _gfortrani_convert_real
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __strtod referenced in function _gfortrani_convert_real
libgfortran.a(read.o) : error LNK2019: unresolved external symbol __strtold referenced in function _gfortrani_convert_real
libgfortran.a(fileline.o) : error LNK2019: unresolved external symbol __ms_vsnprintf referenced in function snprintf.constprop.0
libgfortran.a(dwarf.o) : error LNK2001: unresolved external symbol __ms_vsnprintf
test.exe : fatal error LNK1120: 10 unresolved externals

Мне интересно, есть ли еще несколько библиотек MinGW, которые мне нужно связать, чтобы избавиться от этих неразрешенных внешних элементов? Или, возможно, привязка пути к библиотекам MinGW решит эту проблему, и как я могу сделать это из командной строки Visual Studio? Я думаю, должен быть более простой способ связать очень простой код C и Fortran с использованием Visual Studio и MinGW GFortran.

...