找回密码
 注册
查看: 2840|回复: 3

[原创]用Borland C++Builder调用Fortran动态链接库实例

[复制链接]
发表于 2003-9-30 12:40:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
[这个贴子最后由iceArcher在 2003/09/30 01:20pm 第 1 次编辑]

在软件编程过程中,我们常常需要利用Fortran数值计算快的优点,因此实现由其他软件
调用Fortran的DLL(用PowerStation就可以生成)就显得十分重要了。
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "CallDll.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
//C++Builder调用Fortran动态链接库函数Mysub示例
void __fastcall TForm1::Button2Click(TObject *Sender)
{
void (_stdcall* myegg)(double,double*,char*);
HINSTANCE hMyInst;
hMyInst=LoadLibrary("MyDll.dll");
if(hMyInst==NULL)
{
Edit1->Text="Can't Open Dll";
}
//先用TDump.exe Mydll.dll命令获取_MYSUB@20
(FARPROC&)myegg=GetProcAddress(hMyInst,"_MYSUB@20");
if(myegg==NULL)
{
Edit1->Text="Load Error";
}
else
{
double x,y;
char cha[50]="";
x=3.4;
myegg(x,&y,cha);
Edit1->Text=FloatToStr(y);
Edit2->Text=AnsiString(cha);
}
FreeLibrary(hMyInst);
}
//---------------------------------------------------------------------------
//Fortran生成文件“Mydll.dll”
/*
////////////////////////////////////////////////////////////////////////////////
subroutine mysub(ch)
!ms$attributes dllexport:: mysub
!ms$attributes value::x
!ms$attributes reference::y,ch
implicit none
double precision:: x,y
character(len=50):: ch
ch = "Hello Me!"
y  = 3.0D0*x
return
end subroutine mysub
注意:如果是双精度值数据,则在Fortran中的常数必须有D结尾,如2.2D0,0.22D+1等,
否则C++认为此常数为float类型,会带来误差。
////////////////////////////////////////////////////////////////////////////////
subroutine mysub(x,im)
!ms$attributes dllexport:: mysub
!ms$attributes value::im
!ms$attributes reference::x
implicit none
integer i,im
double precision,dimension(im):: x
do i=1,im
   x(i) = i*2.2d0
enddo
return
end subroutine mysub
C++Call:
void (_stdcall* myegg)(double*,int);
......
double x[30];
myegg(x,30);
Edit1->Text=x[3];
......
Result: Edit1->Text= 8.8
////////////////////////////////////////////////////////////////////////////////
从C++Builder传递多维数组x(im,jm,km)/or:x[im][jm][km]/到Fortran中:
Fortran Code:
subroutine mysub(x,im,jm,km)
!ms$attributes dllexport:: mysub
!ms$attributes value::im,jm,km
!ms$attributes reference::x
implicit none
integer i,j,k,im,jm,km
double precision,dimension(im,jm,km):: x
do i = 1, im
do j = 1, jm
do k = 1, km
    x(i,j,k) = i+j+k
enddo
enddo
enddo
return
end subroutine mysub
从数据结构上讲,多维数组实际上是用一维数组实现的。
由于多维数组的顺序存储方式不同:
Fortran按列优先顺序(所有数组元素按列向量依次排列,第j+1个列向量紧跟在第
j个列向量后面,因此下标变动得最快的是第一维);
C/C++按行优先顺序(所有数组元素按行向量依次排列,第i+1个行向量紧跟在第i
个行向量后面,因此下标变动得最快的是最后一维);
所以在调用动态链接库中的Fortran程序时,调用语句中参数im,jm,km的位置顺
序刚好相反。
* 设im=2,jm=3,km=4,则x(im,jm,km)在内存中的存储形式
Fortran:      index
(1,1,1)    3
(2,1,1)         4
(1,2,1)         4
(2,2,1)         5
(1,3,1)         5
(2,3,1)         6
(1,1,2)         4
(2,1,2)         5
......         ...
C++:           index
(1,1,1)         3
(1,1,2)         4
(1,1,3)         5
(1,1,4)         6
(1,2,1)         4
(1,2,2)         5
......         ...
C++ Code(Part):
......
void (_stdcall* myegg)(double*,int,int,int);
......
(FARPROC&)myegg=GetProcAddress(hMyInst,"_MYSUB@16");
......
int i,j,k,id,im,jm,km;
im=2;jm=3;km=4;
double *x;
x = new double [im*jm*km];
myegg(x,km,jm,im);          //按列优先的方式传递给Fortran
fstream mfile;
mfile.open("xx.dat",ios:ut);
for(i=0;i<im;i++)
for(j=0;j<jm;j++)
for(k=0;k<km;k++)
{
id=i*jm*km+j*km+k;  // 继续按C++的行优先计算下标
mfile<<"i="<<i+1<<" j="<<j+1<<" k="<<k+1;
mfile<<" x="<<x[id]<<endl;
}
mfile.close();
delete [] x;
......
由于C++和Fortran处理的数组都不是同一种形式,在程序中处理起来很不方便,因此可以
按照x(i,j,k)行优先的惯例传递im,jm,km,但在C++中却按列优先的顺序计算下标:
......
x = new double [im*jm*km];
myegg(x,im,jm,km);
......
id=k*jm*im+j*im+i;
......
对于高于三维的数组类似处理,如x(nb,im,jm,km)
......
nb=2,im=3;jm=4;km=5;
double *x;
x = new double [nb*im*jm*km];
myegg(x,nb,im,jm,km);
......
id=k*jm*im*nb+j*im*nb+i*nb+n;
......
delete [] x;
......
*/
//---------------------------------------------------------------------------
发表于 2004-1-3 09:35:34 | 显示全部楼层

[原创]用Borland C++Builder调用Fortran动态链接库实例

icearcher兄,谢谢!顶!
发表于 2004-1-8 15:35:29 | 显示全部楼层

[原创]用Borland C++Builder调用Fortran动态链接库实例

看起来还是很麻烦呀
windows下还是没有像gcc、pgc那样支持c/c++/f77/f9x的编译器家族,这样的东西对混编是非常方便的。
发表于 2005-1-29 14:39:15 | 显示全部楼层

[原创]用Borland C++Builder调用Fortran动态链接库实例

iceArcher, 如果要向DLL中传递数据,有什么办法吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表