||
操作系统:Win10 Professional
IDE:VS2015
C#编译环境:.NET Framework 4.5.2
Fortran编译环境:Intel Parallel Studio XE 2015
Fortran生成动态链接库即dll文件(计算部分),C#做界面调用dll(交互界面)。
计算大数阶乘部分参考http://fcode.cn/algorithm-50-1.html.
C#调用Fortran生成的dll要点:
Fortran部分:
1.!DEC$ ATTRIBUTES DLLEXPORT::FFACTORIAL表示生成的dll函数可被外界调用;
2.!DEC$ ATTRIBUTES ALIAS:'FFACTORIAL'::FFACTORIAL,Fortran是大小写不敏感的语言,即ABCD、AbCd和abcd在Fortran编译器看来都是一样的,但是其他大多数语言包括C#是大小写敏感的,A和a在C#中是不同的。Fortran生成的Function或者Subroutine名不管代码中是大写还是小写,最终编译后都是大写的,比如本文中子程序ffactorial在代码中可以写成ffactorial或者FFACTORIAL或者Ffactorial甚至FfAcToRiAl,最终编译后在dll中统一为FFACTORIAL。VS命令输出dumpbin /exports XXX.dll即可导出函数信息。ALIAS属性可以为函数定义别名,限定其混合书写。
3.!DEC$ ATTRIBUTES STDCALL::FFACTORIAL,stdcall是函数调用约定的一种,函数调用约定主要约束了两件事:参数从右向左压入堆栈,函数被调用者修改堆栈。
4.!DEC$ ATTRIBUTES REFERENCE::nLbound, nUbound ,FirstNumber , LastNumber,参数传递方式为引用传递。
C#部分:
1.using System.Runtime.InteropServices;增加对动态链接库操作的引用;
2.[DllImport(@"F:\Fortran\FFACTORIAL\FFACTORIAL\Release\FFACTORIAL.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void FFACTORIAL(ref long a,ref long b,ref double FirstNumber,ref long LastNumber, long[] LongAns);DllImport属性装载传递过来的子例程和相对应的参数;函数调用约定为stdcall,ref代表参数引用传递。
结果演示:
Fortran部分代码:
!nLbound阶乘下界,nUbound阶乘上界(最大32767)
!FirstNumber结果底数部分,LastNumber结果指数部分,ires结果各位具体值
subroutine ffactorial( nLbound, nUbound ,FirstNumber , LastNumber, ires)
!编译功能选项 !DEC$ ATTRIBUTES
!可被外界调用的dll函数
!DEC$ ATTRIBUTES DLLEXPORT::FFACTORIAL
!使用ALIAS(别名)属性指定导出函数名
!DEC$ ATTRIBUTES ALIAS:'FFACTORIAL'::FFACTORIAL
!STD调用方式
!DEC$ ATTRIBUTES STDCALL::FFACTORIAL
!参数传递方式为引用传递(数组默认是引用传递)
!DEC$ ATTRIBUTES REFERENCE::nLbound, nUbound ,FirstNumber , LastNumber
Use, Intrinsic :: ISO_FORTRAN_ENV, only : OUTPUT_UNIT
implicit none
integer(8),parameter :: pmax = 10**13, len = 10300
integer(8),intent(in) :: nLbound, nUbound
integer(8),intent(out) :: LastNumber, ires(len)
real(8),intent(out)::FirstNumber
integer(8) nL, nU
integer(8) i, j, m, n, cc
character ch*24, CnLbound*5, CnUbound*5
write(CnLbound,'(I5)')nLbound
write(CnUbound,'(I5)')nUbound
ires=0; ires(1)=1
nL = 1; nU = 1
do i = nLbound, nUbound
ires(nL:nU) = ires(nL:nU) * i
n = 0
do j = nL, nU
if( ires(j)/=0 ) then
m = ires(j) / pmax
ires(j+1) = ires(j+1) + m
ires(j) = ires(j) - pmax*m
n = 1
else if( n==0 ) then
nL = j
end if
end do
if( ires(nU+1) > 0 ) nU = nU + 1
end do
open(OUTPUT_UNIT,file=CnLbound//'_'//CnUbound//'.txt')
write(ch,*) ires(nU)
ch = adjustl(ch)
m = len_trim(ch)
n = (nU-1)*13+m-1
read(ch(1:m),'(I<m>)')cc
FirstNumber=cc/10.0_16**(m-1)
write(ch,*) n
ch = adjustl(ch)
if( nU > 1 ) then
write(OUTPUT_UNIT,'(i<m>)',advance='no') ires(nU)
write(OUTPUT_UNIT,'(<nu-1>i13.13)') ires(nU-1:1:-1)
else
write(OUTPUT_UNIT,'(i<m>)') ires(nU)
end if
close(OUTPUT_UNIT)
LastNumber=n
end subroutine ffactorial
C#代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
namespace CF
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
long a, b;
long LastNumber = new long();
long[] LongAns = new long[10300];
double FirstNumber = new double();
a = Convert.ToInt32(LowNumber.Text);
b = Convert.ToInt32(UpNumber.Text);
FFactorial.FFACTORIAL(ref a, ref b, ref FirstNumber, ref LastNumber, LongAns);
this.AnswerNumber.Text = Convert.ToString(FirstNumber) + "E" + Convert.ToString(LastNumber);
int k = 10299;
for (int i = 10299; LongAns[i] == 0; i = i - 1)
k = k - 1;
int j = k;
for (int i = k; LongAns[i] != 0; i = i - 1)
{
this.LongAnswer.Text += Convert.ToString(LongAns[i]);
j = j - 1;
}
for (int i = j; i >= 0; i = i - 1)
this.LongAnswer.Text += "0000000000000";
}
}
public class FFactorial
{
[DllImport(@"F:FortranFFACTORIALFFACTORIALReleaseFFACTORIAL.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void FFACTORIAL(ref long a,ref long b,ref double FirstNumber,ref long LastNumber, long[] LongAns);
}
}
参考文献:
[1] Fcode研讨团队《Fortran求大数阶乘》 http://fcode.cn/algorithm-50-1.html.
[2]C#和Fortran的混合编程http://blog.csdn.net/HanYanBin/article/details/5723101
[3]《Fortran95程序设计》彭国伦
[4]《C#高级编程(第9版)》
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-23 18:27
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社