2009-12-31 2 views
0

Я хочу получить доступ к некоторым подпрограммам из сторонних DLL. Функции используют STDCALL в качестве вызывающего соглашения.gfortran, DLL, underscore

Запуск dumpbin /export foo.dll дает мне что-то вроде:

 ... 
     7 6 00004B40 [email protected] 
     ... 

Я скомпилировать свой код, используя:

 gfortran test.f90 -o test.exe -Wl,foo.dll 

Я получаю сообщение об ошибке: undefined reference to '_foo_' (обратите внимание на знак подчеркивания).

Я попытался добавить флаг компиляции -mrtd, а также другие флаги, которые я googled, все безрезультатно.

Как я могу заставить fortran не добавлять символы подчеркивания?


редактировать: Немного разъяснений по порядку.

  1. У меня есть существующая DLL, к которой у меня нет источника.
  2. Эта DLL написана на Visual Basic, если это помогает.
  3. Я хочу назвать эту DLL от fortran.
  4. Когда я пишу в test.f90: Foo(1.0d0) я получаю ошибку undefined reference to '_foo_' тяг

ответ

3

Пробовали ли вы -fno-Подчеркивая?

Я нашел сообщение от Tobias Burnus (разработчик gfortran) по адресу http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html (ближе к концу) - он рекомендует использовать директивы компилятора вместо -mrtd.

+0

Hmph. Спасибо за ответ, но я хочу вызвать * существующую * DLL * из * Fortran. Я редактирую вопрос, чтобы сделать его более понятным. –

+0

Да, я понял, что вы вызывали существующую DLL из Fortran. Из сообщения об ошибке Fortran вызывает «_foo_», хотя, по-видимому, DLL имеет «Foo». Поэтому вы хотите сообщить компилятору Fortran, чтобы он не добавлял подчеркивания к обычным именам, что и делает параметр компилятора -fno-underscoring. –

+0

Извините, предоставленная ссылка говорила о вызове fortran DLL. По какой-то причине '-fno-underscoring' не помогает. Когда я компилирую с '-v', я вижу, что он действительно используется, но он не меняет сообщение об ошибке. Я попробую это на другой установке, возможно ... –

1

Просто хотел бы остановиться на M.S.B's -fno-underscoring answer: Вы можете столкнуться с проблемами при использовании f2c & g77. От the gfortran documentation:

With -funderscoring in effect, GNU Fortran appends one underscore to external names with no underscores. This is done to ensure compatibility with code produced by many UNIX Fortran compilers.

Caution: The default behavior of GNU Fortran is incompatible with f2c and g77, please use the -ff2c option if you want object files compiled with GNU Fortran to be compatible with object code created with these tools.

Use of -fno-underscoring is not recommended unless you are experimenting with issues such as integration of GNU Fortran into existing system environments (vis-à-vis existing libraries, tools, and so on).

Вам может понадобиться перекомпилировать DLL с чем-то вроде -fno-underscoring, чтобы удалить подчеркивание из DLL.

У меня возникли проблемы с переносимостью, связанные с префиксом/суффиксом подчеркивания некоторыми компиляторами Fortran: некоторые компиляторы _prefix или suffix_ по умолчанию, а другие нет! Мое решение было директивы препроцессора:

#ifdef LC_UNSC 
#define GET_DIP_MOMENT get_dip_moment_ 
#elif LC_NOUNSC 
#define GET_DIP_MOMENT get_dip_moment 
#endif 
... 
    call GET_DIP_MOMENT() 
+0

К сожалению, у меня нет доступа к источнику DLL (который, как я понимаю, написан на Visual Basic, всех языков) –

0

Другой подход заключается в использовании ISO C Связывание Fortran 2003, который поддерживается gfortran> = 4.3. Это автоматически будет использовать соглашения о сокращении C (т. Е., Вероятно, нет), а не в компиляторе Fortran. Он также даст вам контроль над случаем (заглавностью) имен подпрограмм, если Windows Linker позаботится об этом. Фортран нечувствителен к регистру, поэтому вы можете вызвать подпрограммы Fortran в любом случае - возможно, компоновщик преобразуется в нижний регистр.

Включая следующий «интерфейс» в объявлениях подпрограммы Fortran, который вызывает «Foo», описывает Foo как подпрограмму C (функция void) с единственным аргументом двойного типа - вход/выход Fortran или указатель в C.Если Foo имеет другие свойства, интерфейс необходимо изменить. Предложение «bind» указывает имя, чувствительное к регистру, для предоставления компоновщику. Если вы вызываете Foo из нескольких подпрограмм Fortran, тогда лучше всего поместить интерфейс в модуль и «использовать» его из каждой процедуры Fortran.

Это предназначено для C - возможно, оно будет работать для Visual Basic. Связывание ISO C дает большой контроль, поэтому, если это не сработает, возможно, некоторые изменения будут.

interface VisBasSubs 

    subroutine foo (DoubleArg) bind (C, name="Foo") 

     use iso_c_binding, only: c_double 
     real (kind=c_double), intent (inout) :: DoubleArg  

    end subroutine foo 

end interface VisBasSubs 
+0

Не работает, используя атрибут компилятора необходим. –

+0

У моего первого ответа была ссылка на инструкции о директивах gcc-компилятора для stdcall. –

2

Вам необходимо объединить использование ISO_C_BINDING с атрибутами компилятора. Вы действительно должны прочитать раздел Mixed-Language Programming руководства gfortran. Он дает хорошие советы, которые можно использовать и с другими компиляторами. В частности, в вашем случае вам нужно stdcall атрибут:

interface VisBasSubs 

    subroutine foo (DoubleArg) bind (C, name="Foo") 
     !GCC$ ATTRIBUTES stdcall :: foo 
     use iso_c_binding, only: c_double 
     real (kind=c_double), intent (inout) :: DoubleArg  

    end subroutine foo 

end interface VisBasSubs 

Обратите внимание на строку с stdcall, это то, что должно сделать его работу.