VC 2005 如何调用fortran 库函数
采用VC2005intelc++11.0和intelfortran11.0如何让c++项目调用fortran建立的库呢?例如有以下fortran函数SUBROUTINEM...
采用VC2005 intel c++11.0 和intel fortran 11.0
如何让c++项目调用fortran建立的库呢?
例如
有以下fortran 函数
SUBROUTINE MYCALL()
IMPLICIT NONE
WRITE(*,*) "调用成功!"
END SUBROUTINE MYCALL
该如何c++中调用,下面的调用出现问题
error LNK2019: 无法解析的外部符号 _mycall_,该符号在函数 _main 中被引用
// 错误的c++调用如下:
#include <iostream>
#include <windows.h>
extern "C" void mycall_();
int main()
{
int n=3;
mycall_();
return 0;
} 展开
如何让c++项目调用fortran建立的库呢?
例如
有以下fortran 函数
SUBROUTINE MYCALL()
IMPLICIT NONE
WRITE(*,*) "调用成功!"
END SUBROUTINE MYCALL
该如何c++中调用,下面的调用出现问题
error LNK2019: 无法解析的外部符号 _mycall_,该符号在函数 _main 中被引用
// 错误的c++调用如下:
#include <iostream>
#include <windows.h>
extern "C" void mycall_();
int main()
{
int n=3;
mycall_();
return 0;
} 展开
展开全部
正好最近一个项目需要在C/C++程序中调用Fortran写的DLL, 有一些心得记录下来.
我用的C/C++集成环境是VC8(.Net 2005), Fortran编译用了Intel Visual Fortran Compiler 9.1, 在WindowsXP SP2上进行开发.
调试的时候, Dependency Walker这个软件很有用, 能直接看到编译出来的DLL中的信息.
首先写了一个fortranlib.dll, 很简单, 只有一个函数, 代码如下:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
然后写了一个callfortran.exe, 代码如下:
#include <iostream>
extern "C" double __stdcall testfunc(double x, double y);
int main(int argc, char* argv[])
{
double a = 2.0;
double b = 1.0;
double c;
c = testfunc(a, b);
std::cout << b << std::endl;
return 0;
}
需要将fortranlib.lib作为callfortran.exe的additional dependency才能编译通过, 然后就可以work了.
如果两边都采用C的calling convention, 也可以编译通过且正确运行. 修改如下:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, C::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __cdecl testfunc(double x, double y);
另外, 如果要采用REFERENCE型的传参规则, 以stdcall为例, 应改为:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES REFERENCE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __stdcall testfunc(double* x, double* y);
要注意的几点:
1. Fortran忽略大小写, 如果代码中函数名含大写, 那么在编译出来的库中, 函数名称全部都被转成小写了(用Dependency Walker可以看到). 而C/C++是区分大小写的, 所以在C/C++中声明extern的函数时必须用小写的名字, 除非fortran函数被"!DEC$ ATTRIBUTE ALIAS"指令强制化名为含大写字母的名称.
2. Fortran中的几个涉及到Calling Convention和传参规则的"!DEC$"指令, 最好都显式的写出来. 因为不同的编译器以及在不同的操作系统上, 默认的编译行为都很可能不一样. 采用默认行为容易遇到一些原因很难查清的问题. C/C++也一样, 最好显式的写清楚是__cdecl还是__stdcall.
我用的C/C++集成环境是VC8(.Net 2005), Fortran编译用了Intel Visual Fortran Compiler 9.1, 在WindowsXP SP2上进行开发.
调试的时候, Dependency Walker这个软件很有用, 能直接看到编译出来的DLL中的信息.
首先写了一个fortranlib.dll, 很简单, 只有一个函数, 代码如下:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
然后写了一个callfortran.exe, 代码如下:
#include <iostream>
extern "C" double __stdcall testfunc(double x, double y);
int main(int argc, char* argv[])
{
double a = 2.0;
double b = 1.0;
double c;
c = testfunc(a, b);
std::cout << b << std::endl;
return 0;
}
需要将fortranlib.lib作为callfortran.exe的additional dependency才能编译通过, 然后就可以work了.
如果两边都采用C的calling convention, 也可以编译通过且正确运行. 修改如下:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, C::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __cdecl testfunc(double x, double y);
另外, 如果要采用REFERENCE型的传参规则, 以stdcall为例, 应改为:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES REFERENCE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __stdcall testfunc(double* x, double* y);
要注意的几点:
1. Fortran忽略大小写, 如果代码中函数名含大写, 那么在编译出来的库中, 函数名称全部都被转成小写了(用Dependency Walker可以看到). 而C/C++是区分大小写的, 所以在C/C++中声明extern的函数时必须用小写的名字, 除非fortran函数被"!DEC$ ATTRIBUTE ALIAS"指令强制化名为含大写字母的名称.
2. Fortran中的几个涉及到Calling Convention和传参规则的"!DEC$"指令, 最好都显式的写出来. 因为不同的编译器以及在不同的操作系统上, 默认的编译行为都很可能不一样. 采用默认行为容易遇到一些原因很难查清的问题. C/C++也一样, 最好显式的写清楚是__cdecl还是__stdcall.
展开全部
VC 2005和Fortran混合编程借助于Fortran生成的DLL进行(采用C默认的传址方式进行函数参数传递)方法和实例:
1.Fortran
生成DLL
新建Fortran
DLL程序test1.f
添加如下代码:
! test1.f90
!
! FUNCTIONS/SUBROUTINES
exported from test1.dll:
! test1 -
subroutine
!示例没有返回值的子例程
subroutine
test1(a,b)
! Expose subroutine test1 to
users of this DLL
!
!DEC$ ATTRIBUTES
C,DLLEXPORT::test1
! Variables
! Body of
test1
integer a,b
integer sum
sum=a+b
return
end subroutine
test1
!示例有返回值的整数四则运算
!两数相加
function
add(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::add
integer
a,b,add
add=a+b
return
end
!两数相减
function
abstract(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::abstract
integer
a,b,abstract
abstract=a-b
return
end
!两数相乘
function
multiply(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::multiply
integer
a,b,multiply
multiply=a*b
return
end
!两数相除
(需要添加考虑被除数是否为0以及能否整除的判断)
function
divided(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::divided
integer
a,b,divided
divided=a/b
return
end
编译后生成test1.dll,test1.obj等文件。其中这两个文件是我们在VC中调用所需要的。
1.Fortran
生成DLL
新建Fortran
DLL程序test1.f
添加如下代码:
! test1.f90
!
! FUNCTIONS/SUBROUTINES
exported from test1.dll:
! test1 -
subroutine
!示例没有返回值的子例程
subroutine
test1(a,b)
! Expose subroutine test1 to
users of this DLL
!
!DEC$ ATTRIBUTES
C,DLLEXPORT::test1
! Variables
! Body of
test1
integer a,b
integer sum
sum=a+b
return
end subroutine
test1
!示例有返回值的整数四则运算
!两数相加
function
add(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::add
integer
a,b,add
add=a+b
return
end
!两数相减
function
abstract(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::abstract
integer
a,b,abstract
abstract=a-b
return
end
!两数相乘
function
multiply(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::multiply
integer
a,b,multiply
multiply=a*b
return
end
!两数相除
(需要添加考虑被除数是否为0以及能否整除的判断)
function
divided(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::divided
integer
a,b,divided
divided=a/b
return
end
编译后生成test1.dll,test1.obj等文件。其中这两个文件是我们在VC中调用所需要的。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询