我正在尝试使用命令行编译混合程序。
编译工具是intel visual fortran 2013和VS 2013。
我搜索了一下,发现使用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 / link 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
另外,我搜索了一下,有人说__stdcall
不是必要的,我删除但仍然有错误:
error LNK2019: unresolved external symbol _FACT referenced in function _main
error LNK2019: unresolved external symbol _PYTHAGORAS referenced in function _main
我认为它可能与this相同。但是我自己无法解决它。
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
它仍然不起作用。
答案 0 :(得分:1)
C / C ++区分大小写,因此如果您致电FACT
,则必须将其声明为FACT
,而不是fact
。或者相反。
你需要将你的函数(在C ++代码中)声明为extern "C"
,以禁用特定于C ++的名称修改。
__stdcall
确实是Fortran函数的正确调用约定(默认情况下)。
Fortran不区分大小写(默认情况下,但可以通过编译器选项进行更改,这是愚蠢的)。我相信英特尔Fortran编译器为Fortran函数生成全大写符号(用于链接目的)(例如,名为&#34的函数; Fact&#34;将导出为&#34; FACT&#34;)。因此,您需要在C ++声明中匹配该情况。我不确定它与Fortran符号的结合方式(全大写或全小写),所以,如果一个不起作用,请尝试另一个。
编辑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
,而对于Fortran中的[VALUE]
类型,它也应该通过C / C ++中的值传递...至少,这是我对它的理解(但就像我说的,我不是Fortran专家)。