Смешанное программирование: вызов FORTRAN из C ++

0

Я пытаюсь скомпилировать смешанную программу с командной строкой.

Инструмент компиляции - это интеллектуальный fortran 2013 и VS 2013.

Я googled вокруг и нашел, что использование dll проще, чем lib.

Поэтому я попытался скомпилировать исходный файл fortran как файл dll

мой источник Fortran:

!  forsubs.f90 
!
!  FUNCTIONS/SUBROUTINES exported from FORSUBS.dll:
! FORSUBS      - subroutine 
!
INTEGER*4 FUNCTION Fact (n)
   !DEC$ ATTRIBUTES DLLEXPORT::Fact
      INTEGER*4 n [VALUE]
      INTEGER*4 i, amt
      amt = 1
      DO i = 1, n
        amt = amt * i
      END DO
      Fact = amt
   write(*,*)"Mixed calls succeed!"
END
SUBROUTINE Pythagoras (a, b, c)
   !DEC$ ATTRIBUTES DLLEXPORT::Pythagoras
      REAL*4 a [VALUE]
      REAL*4 b [VALUE]
      REAL*4 c [REFERENCE]
      c = SQRT (a * a + b * b)
END

мой источник C++: c_main.cpp

/*     File CMAIN.C   */

#include <stdio.h>

extern int __stdcall fact(int* n);
extern void __stdcall pythagoras(float* a, float* b, float *c);

int main()
{
    float c;
    printf("Factorial of 7 is: %d\n", FACT(7));
    PYTHAGORAS (30, 40, &c);
    printf("Hypotenuse if sides 30, 40 is: %f\n", c);
}

Сначала я скомпилировал источник fortran:

ifort/dll forsubs.f90

и получил forsubs.dll и forsubs.lib.

Во-вторых, я собрал свой источник C++:

cl c_main.cpp/ссылка forsubs.lib

Однако у меня есть ошибка:

D:\c_f\c_f_dll\c_main.cpp(11) : error C3861: "FACT":  identifier not found
D:\c_f\c_f_dll\c_main.cpp(12) : error C3861: "PYTHAGORAS":  identifier not found

Кроме того, я попытался загрузить dll по-другому, используя:

 HINSTANCE hLibrary=LoadLibrary("forsubs.dll"); 
 if(hLibrary==NULL)
 {
  cout<<"can't find the dll file"<<endl;
  return -1;
 }

Но я получил "не могу найти файл dll" каждый раз, когда я уверен, что forsubs.dll находится в папке.

Я плохо разбираюсь в C++ и не могу понять, как скомпилировать его, помогите!

редактировать

Странный! Я отредактировал свою программу как ответ @Mikael Persson, но все еще получил ошибку.

error LNK2019: unresolved external symbol _FACT@4 referenced in function _main
error LNK2019: unresolved external symbol _PYTHAGORAS@12 referenced in function _main

Кроме того, я googled вокруг и кто-то сказал __stdcall не является обязательным, я удаляю, но все еще получил ошибку:

error LNK2019: unresolved external symbol _FACT referenced in function _main
error LNK2019: unresolved external symbol _PYTHAGORAS referenced in function _main

Я думал, что это может быть та же проблема, как это. Но я не могу решить это сам.

PS: информация о моей dll и lib:

D:\c_f\c_f_dll>dumpbin /exports forsubs.lib
Microsoft (R) COFF/PE Dumper Version 12.00.30501.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file forsubs.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  FACT
                  PYTHAGORAS

  Summary

          C3 .debug$S
          14 .idata$2
          14 .idata$3
           8 .idata$4
           8 .idata$5
           C .idata$6

D:\c_f\c_f_dll>dumpbin /exports forsubs.dll
Microsoft (R) COFF/PE Dumper Version 12.00.30501.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file forsubs.dll

File Type: DLL

  Section contains the following exports for forsubs.dll

    00000000 characteristics
    5477F1C5 time date stamp Fri Nov 28 11:53:41 2014
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00001000 FACT
          2    1 000010B0 PYTHAGORAS

  Summary

        1000 .data
        1000 .pdata
        1000 .rdata
        1000 .reloc
        1000 .text

Edit2

Also, I have tried to add a header:
#ifdef FORSUBS_EXPORTS
#define FORSUBS_API __declspec(dllexport) 
#else
#define FORSUBS_API __declspec(dllimport) 
#endif

он все еще не работает.

  • 0
    я не знаю как вы, но в dll-файле на Фортране были только функции, но не было оператора dllmain switch или функции createthread. Не забудьте иметь правильный каталог / путь для loadlibrary.
  • 0
    @Amadan Амадан, привет, я добавил "C" в код, но получил ту же ошибку. Я думал, что __stdcall необходим, зависит от вопроса "Смешанное программирование: вызов FORTRAN из C". Есть идеи со вторым способом в моем вопросе?
Показать ещё 3 комментария
Теги:
dll
fortran

1 ответ

0

C/C++ чувствителен к регистру, поэтому, если вы вызываете FACT, то он должен быть объявлен как FACT, а не как fact. Или наоборот.

И вам нужно объявить свои функции (в коде C++) как extern "C", чтобы отключить C++ -специфическое имя, которое было бы принято иначе.

И __stdcall - действительно правильное соглашение о вызове для функций Fortran (по умолчанию).

Fortran не учитывает регистр (по умолчанию, но его можно изменить с помощью параметров компилятора, что глупо). Я считаю, что компилятор Intel Fortran генерирует символы всех верхних регистров (для целей привязки) для функций Fortran (например, функция "Факт" будет экспортироваться как "ФАКТ"). Таким образом, вам нужно сопоставить этот случай с объявлением C++. Я не уверен, как это происходит с символами Фортрана (либо в верхнем регистре, либо в любом случае), поэтому, если он не работает, попробуйте другой.

EDIT 2:

Что касается прототипов, я считаю, что это правильные формы в C++ (я не уверен, потому что я довольно ржавый, когда речь заходит о Fortran):

#include <stdint.h>  // in C, or <cstdint> in C++ (but must use std::int32_t)

extern "C" __declspec(dllimport) int32_t __stdcall FACT(int32_t n);
extern "C" __declspec(dllimport) void __stdcall PYTHAGORAS(float a, float b, float *c);

Обратите внимание, что для 4-байтового целого вам необходимо использовать int32_t, а для типов [VALUE] в Fortran он также должен быть передан по значению в C/C++... по крайней мере, что мое понимание этого ( но, как я уже сказал, я не эксперт по Фортрану).

  • 0
    Привет, я отредактировал свой код, но получил еще одну ошибку, я обновил свой вопрос.
  • 0
    @PaleNeutron Извините ... я уже давно не использую DLL, библиотеки импорта MSVC или Windows ... поэтому я немного разбираюсь в этом и не могу ничего проверить. Я считаю, что если вы связываетесь с библиотекой импорта (файл __declspec(dllimport) ), то вам нужно добавить __declspec(dllimport) в объявления функций между extern "C" и типами возвращаемых данных.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню