Загрузка функции Fortran из динамической библиотеки: Debug vs Release

Я написал некоторый код для загрузки динамической библиотеки, которая была скомпилирована в Fortran. Среди экспортируемых функций в библиотеке Фортрана есть экспортируемые сеттеры и геттеры. Я пытаюсь загрузить эти установщики и получатели, используя Windows API. Хотя это работает для моего кода, встроенного в отладку. Он не работает с моим кодом, встроенным в релиз. В релизе, когда я пытаюсь пройти 1.0f Через set() я вижу 0.0f в отладчике, когда я вхожу в код Fortran.

Изменить: еще одно наблюдение, которое я забыл упомянуть. Если бы я только загрузить setValue() функция. Моя проблема полностью уходит. Только когда я загружаю дополнительные функции из библиотеки, у меня появляются проблемы, которые я вижу.

Составители

  • Intel Fortran 2017, обновление 5
  • Visual Studio 2017 v15.5.2

отладка

Я определил, что когда мой код C ++ скомпилирован в выпуске, мой загруженный set() функция пройдет 0.0f в Фортран функции. Это было обнаружено путем загрузки отладочной версии библиотеки fortran и запуска ее через отладчик Visual Studio. Выполнение того же самого с отладочной сборкой моего кода дает правильное значение, передаваемое функции fortran.

Я попробовал следующее в попытке выяснить, что происходит:

  • Попытка загрузки двоичных файлов Debug и Release скомпилированного Fortran в обеих сборках Debug и Release моего загрузчика. Работает только для моей сборки Debug загрузчика.
  • Перестроен код Fortran, проверяющий флаги компилятора, такие как Mutithreaded Debug DLL для Debug и Multithreaded DLL для выпуска.
  • Выполнен дамп бинарного файла fortran для проверки правильности загрузки адреса функции; они есть.

FORTRAN

    REAL FUNCTION getValue()
!DEC$ ATTRIBUTES DLLEXPORT, c:: getValue
IMPLICIT NONE
INCLUDE 'VALUE.CMN'

getValue = VAL
RETURN
END FUNCTION getValue

SUBROUTINE setValue(x)
!DEC$ ATTRIBUTES DLLEXPORT, c:: setValue
IMPLICIT NONE
INCLUDE 'VALUE.CMN'

REAL, INTENT(IN) :: x

VAL = x

END SUBROUTINE setValue

C ++

const auto handle = reinterpret_cast<HMODULE>(LoadLibrary("fortran_value.dll"));

typedef void(*Set)(float&);
typedef float(*Get)(void);

const auto set = reinterpret_cast<Set>(GetProcAddress(handle, "setvalue"));
const auto get = reinterpret_cast<Get>(GetProcAddress(handle, "getvalue"));

auto value = 1.0f;

// 0.0f gets set to the internal fotran variable when this code is compile in release.
set(value);

// Only succeeds when this code is compiled in Debug.
// get() returns 0.0f when this code is compiled in Release.
if(value == get())
{
std::cout << "Success!\n";
}
else
{
std::cout << "Fail!\n";
}

FreeLibrary(handle);

Я в недоумении. Любые мысли или предложения о том, что здесь может происходить?

ПОЛНЫЙ СОВМЕСТНЫЙ ПРИМЕР

Ниже приведены ссылки на полный скомпилированный пример проблемы, с которой я столкнулся. После того, как у вас будет больше времени, чтобы провести с ним. Похоже, мои проблемы связаны с моими попытками создать оболочку с приведенным выше кодом.

fortran_value.dll

fortran_value_test.exe

1

Решение

Прочитав ответы на мой вопрос, я потратил больше времени на отладку кода на фортране и на дальнейшие исследования. Как обсуждалось в ответах на мой вопрос, было несоответствие в соглашениях о вызовах. Используя bind (c) в моем коде на фортране, моя проблема была решена.

Начиная с Fortran 2003 (ISO / IEC 1539-1: 2004 (E)) существует стандартизированный способ генерации объявлений процедур и производных типов и глобальных переменных, которые совместимы с C (ISO / IEC 9899: 1999). связывания (С) атрибут был добавлен для информирования компилятора о том, что символ должен взаимодействовать с C; также добавлены некоторые ограничения. Обратите внимание, однако, что не все функции C имеют эквивалент Fortran или наоборот. Например, ни целые числа без знака C, ни функции C с переменным числом аргументов не имеют эквивалента в Fortran

    REAL FUNCTION getValue() bind(c)
!DEC$ ATTRIBUTES DLLEXPORT :: getValue
IMPLICIT NONE
INCLUDE 'VALUE.CMN'

getValue = VAL
RETURN
END FUNCTION getValue

SUBROUTINE setValue(x) bind(c)
!DEC$ ATTRIBUTES DLLEXPORT :: setValue
IMPLICIT NONE
INCLUDE 'VALUE.CMN'

REAL, INTENT(IN) :: x

VAL = x

END SUBROUTINE setValue
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]