Я пытаюсь скомпилировать смешанную программу с командной строкой.
Инструмент компиляции - это интеллектуальный 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);
}
ifort/dll forsubs.f90
и получил forsubs.dll
и forsubs.lib
.
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
Also, I have tried to add a header:
#ifdef FORSUBS_EXPORTS
#define FORSUBS_API __declspec(dllexport)
#else
#define FORSUBS_API __declspec(dllimport)
#endif
он все еще не работает.
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++... по крайней мере, что мое понимание этого ( но, как я уже сказал, я не эксперт по Фортрану).
__declspec(dllimport)
), то вам нужно добавить __declspec(dllimport)
в объявления функций между extern "C"
и типами возвращаемых данных.
"C"
в код, но получил ту же ошибку. Я думал, что__stdcall
необходим, зависит от вопроса "Смешанное программирование: вызов FORTRAN из C". Есть идеи со вторым способом в моем вопросе?