




已阅读5页,还剩25页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C/C+/Fortran混合编程浅谈(一)直接链接方式 现今流行很多编程语言,在编译型语言中,C/C+/Fortran语言应用非常广泛,C以其效率高效底层操作为著称,C+以其很好的面向对象类框架泛型编程为特点,Fortran则以现世存有大量的计算程序而占有重要的位置,在编程中,集合他们三者的长处是个很好的做法。混合编程有很多方法,以下介绍一下基本方法。 对于各个编译器,如果编译中间的二进制文件.o或.obj的结构相同,则可以直接链接混合编程。 遵循约定:C/C+默认传值,Fortran传址。一、相同编译器家族以gcc家族为例,类似的还有Intel C Compiler和Intel Fortran Compiler等。1、C和Fortran(1)C调用Fortranmain.c#include void sub_fortran_(int *,float *,double *);double function_fortran_(double *);int main() int num_int; float num_float; double num_double; double num; num_int=3; num_float=5.0; sub_fortran_(&num_int,&num_float,&num_double); num=function_fortran_(&num_double); printf(num_int=%dnnum_float=%fnnum_double=%fnnum=%f,num_int,num_float,num_double,num); return 0;sub.f90subroutine Sub_Fortran(NumInt,NumFloat,NumDouble) implicit none integer : NumInt real : NumFloat real(8) : NumDouble NumDouble=NumFloat*NumIntend subroutinereal(8) function Function_Fortran(NumDouble) implicit none real(8) : NumDouble Function_Fortran=sqrt(NumDouble)end functionsub.f90(F2003方式)subroutine Sub_Fortran(NumInt,NumFloat,NumDouble) use ISO_C_BINDING implicit none integer(c_int) : NumInt real(c_float) : NumFloat real(c_double) : NumDouble NumDouble=NumFloat*NumIntend subroutinereal(c_double) function Function_Fortran(NumDouble) use ISO_C_BINDING implicit none real(c_double) : NumDouble Function_Fortran=sqrt(NumDouble)end function链接方法gcc o main.o c main.cgfortran o sub.o c sub.f90gcc o main.exe main.o sub.o或者直接 gcc o main.exe main.c sub.f90输出(2)Fortran调用Cmain.f90program main implicit none interface subroutine sub_c(n1,n2,n3) integer : n1 real : n2 real(8) : n3 end subroutine real(8) function func_c(n3) real(8) : n3 end function end interface integer : n1 real : n2 real(8) : n3,n4 n1=3 n2=5.0 call sub_c(n1,n2,n3) n4=func_c(n3) write(*,*) n1=,n1 write(*,*) n2=,n2 write(*,*) n3=,n3 write(*,*) n4=,n4end programmain.f90(F2003方式)program main use ISO_C_BINDING implicit none interface subroutine sub_c(n1,n2,n3) use ISO_C_BINDING integer(c_int) : n1 real(c_float) : n2 real(c_double) : n3 end subroutine real(c_double) function func_c(n3) use ISO_C_BINDING real(c_double) : n3 end function end interface integer(c_int) : n1 real(c_float) : n2 real(c_double) : n3,n4 n1=3 n2=5.0 call sub_c(n1,n2,n3) n4=func_c(n3) write(*,*) n1=,n1 write(*,*) n2=,n2 write(*,*) n3=,n3 write(*,*) n4=,n4end program sub.c#include void sub_c_(int *,float *,double *);double func_c_(double *);void sub_c_(int *n1,float *n2,double *n3) *n3=pow(*n2,*n1);double func_c_(double *n3) double n4; n4=sqrt(*n3); return n4;链接方式gcc o sub.o sub.cgfortran o main.o main.f90gfortran o main.exe main.o sub.o或是直接gfortran o main.exe main.f90 sub.c输出visualC+与FORTRAN混合编程(2010-04-22 14:15:25) 转载标签: visualcfortran混合编程分类: 科研 原文:/143577510.html本文示例说明用C+编写的主程序调用采用FORTRAN语言编写的子程序的方法。方法一:直接在Microsoft Developer Studio创建包含语言和FORTRAN语言的工程。创建win32 console工程,分别添加cmain.cpp和forsubs.for两个文件,编译链接。#include extern C int _stdcall FACT (int n);extern C void _stdcall PYTHAGORAS (float a, float b, float *c);main() float c; printf(Factorial of 7 is: %dn, FACT(7); PYTHAGORAS (30, 40, &c); printf(Hypotenuse if sides 30, 40 is: %fn, c);C File FORSUBS.FORC INTEGER*4 FUNCTION Fact (n) INTEGER*4 n VALUE INTEGER*4 i, amt amt = 1 DO i = 1, n amt = amt * i END DO Fact = amt END SUBROUTINE Pythagoras (a, b, c) REAL*4 a VALUE REAL*4 b VALUE REAL*4 c REFERENCE c = SQRT (a * a + b * b)write(*,*)你成功了! END方法二:把FORTRAN子程序做成动态链接库供主程序显式调用。(1)创建FORTRAN DLL工程,生成forsubs.dll文件供调用。! 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!ENDSUBROUTINE 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(2)创建win32 console application,调用forsubs.dll。/C+显式调用FORTRAN动态链接库#include #include #include main()/声明调用约定typedef int (_stdcall * FACT)(int n);typedef void (_stdcall * PYTHAGORAS)(float a, float b, float *c);/加载动态库文件HINSTANCE hLibrary=LoadLibrary(forsubs.dll);if(hLibrary=NULL)coutcant find the dll fileendl;return -1;/获得Fortran导出函数FACT的地址FACT fact=(FACT)GetProcAddress(hLibrary,FACT);if(fact=NULL)coutcant find the function file.endl;return -2;/获得Fortran导出函数PYTHAGORAS的地址PYTHAGORAS pythagoras=(PYTHAGORAS)GetProcAddress(hLibrary,PYTHAGORAS);if(pythagoras=NULL)coutcant find the function file.endl;return -2; float c; printf(Factorial of 7 is: %dn, fact(7); pythagoras (30, 40, &c); printf(Hypotenuse if sides 30, 40 is: %fn, c);FreeLibrary(hLibrary); /卸载动态库文件return 0;方法三:把FORTRAN子程序做成库文件供主程序隐式调用。(1)创建FORTRAN DLL工程,生成forsubs.dll和forsubs.lib文件供调用。! forsubs.f90! FUNCTIONS/SUBROUTINES exported from FORSUBS.lib:! FORSUBS - subroutine!INTEGER*4 FUNCTION Fact (n)!ms$if .not. defined(LINKDIRECT)!ms$attributes dllexport:Fact!ms$endif 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!ENDSUBROUTINE Pythagoras (a, b, c)!ms$if .not. defined(LINKDIRECT)!ms$attributes dllexport:Pythagoras!ms$endif REAL*4 a VALUE REAL*4 b VALUE REAL*4 c REFERENCE c = SQRT (a * a + b * b)END(2)创建win32 console application,添加forsubs.lib到工程,动态调用forsubs.dll。#include extern C int _stdcall FACT (int n);extern C void _stdcall PYTHAGORAS (float a, float b, float *c);main() float c; printf(Factorial of 7 is: %dn, FACT(7); PYTHAGORAS (30, 40, &c); printf(Hypotenuse if sides 30, 40 is: %fn, c);C+调用Fortran动态链接库(2010-04-20 14:07:16) 转载标签: c调用fortrandll动态链接库it分类: 科研 /linzch/blog/item/5f5e4d9021873884a977a48a.html这里将详细介绍一下在C+中如何调用用Fortran语言编写函数的问题,即Fortran与C+的混合编程问题。 通常情况下,C与Fortran的混合编程问题是利用动态链接库的方式进行的,换句话说,如果在C/C+中调用Fortran函数,应将Fortran函数按照一定的协议编译为动态链接库,然后即可实现二者的混合编程问题。实现这一目的有两种方式:显示链接与隐式链接,下面通过两个非常简单的实例分别介绍之。编译环境:Fortran:推荐使用Compaq Visual Fortran 6.0以上的版本,C+:Microsoft Visual C+6.0。1. 显式链接,(a) 找开CVF编译器,然后新建一个Fortran DLL工程(选择Fortran Dynamic Link Library),并指定工程名,如下图所示:按确定按钮,然后新建一个Fortran 源文件,并输入以下的Fortran代码:(这里仅为说明问题,实际的问题比下面的代码要复杂得多。)SUBROUTINE OUTPUT(N)!必须声明本函数为输出函数:DLLEXPORT!DEC$ ATTRIBUTES DLLEXPORT:OUTPUTIMPLICIT NONEINTEGER NN=N+10WRITE(*,*) N=,nEND SUBROUTINE OUTPUT经编译,链接后,将在Debug目录下生成两个文件,即dll文件与lib文件。(b) 启动Visual C+6.0,然后新建一个console工程(即Win32 Console Application,当然在MFC中也是完成可行的),如下图所示:按确定按钮,新建一个空的工程后,再新建一个C+源文件,并输入以下的代码:#include #include int main()typedef void (_stdcall * wndProc)(int& );HINSTANCE hLibrary=LoadLibrary(pp.dll); /加载动态库文件if(hLibrary=NULL)cout<<cant find the dll file<<endl;return -1;wndProc test=(wndProc)GetProcAddress(hLibrary,OUTPUT); /获得Fortran导出函数的地址if(test=NULL)cout<<cant find the function file.<<endl;return -2;int n=3;test(n);/调用fortran函数FreeLibrary(hLibrary); /卸载动态库文件return 0;当编译通过后,将由fortran编译器生成的动态库文件(本算例为pp.dll)复制到C+的Debug文件夹中(即mmdebug),然后点击执行即可,程序的动行结果为:2. 隐式链接与上文所介绍的显示链接相比,隐式链接要相对容易一点。下面也通过一个算例进行说明。(1) 建立一个Fortran动态库文件,其方法与上述完全相同,然后在CVF编译器中输入以下的代码:SUBROUTINE OUTPUT(N)!下面为对Fortran函数的声明!ms$if .not. defined(LINKDIRECT)!ms$attributes dllexport : OUTPUT!ms$endifIMPLICIT NONEINTEGER NN=N+10WRITE(*,*) N=,nEND SUBROUTINE OUTPUT编译通过后,将在Fortran工程文件夹的Debug文件夹中生成两个文件,即*.dll文件与*.lib文件。(2) 新建一个C+ Console项目,并新建一个C+文件,然后输入以下的代码:#include <iostream.h>#include <windows.h>/声明函数OUTPUT为extern型的,即是从外部调用的。extern C void _stdcall OUTPUT(int& n);int main()int n=3;OUTPUT(n);return 0;然后将Fortran编译器生成的两个文件(dll文件与lib文件)复制到C+的当前目录下,并将lib文件加入到当前的C+工程项目中,如下图所示:点击菜单“工程添加工程Files”,然后选中pp.lib文件即可,如下图所示:此时即可通过编译,执行此程序,其输出结果如下所示:总结本文通过两个简单的实例详细介绍了如何在C+中调用Fortran函数的两种方法,即显式链接与隐式链接。当然实际中我们所遇到的问题将会比本实例要复杂得多,本文仅作为抛砖引玉之用。显式链接与隐式链接两种方法均各自有其优缺点,但由于隐式链接要比显示链接容易得多,也易于理解,实际的大部分算例均采用这种方式。在linux中操作对于通常的用户,接促C语言的较多,但是,C语言的开发者,有时还想利用高效的Fortran 数据包或者是Fortran语言的开发者想借用C提供的强大辅助功能,为此,为了方便大家对二语言相互调用的学习。这里给出了一些简单的入门性技术介绍。 1. C 调用Fortran 编辑Fortran 源文件 add.f95 subroutine add(a, b, c) implicit none real: a, b, c ! ! the add routine ! c = a+b ! c = a + b write(*,*) a, +, b, =, c return end subroutine add 这里部介绍Fortran的语法格式,add.f95的功能是建立一个add routine 也就是函数。 编译 add.f95 f95 -o add.o -c add.f95 编辑C 主程序main.c 1 #include 2 3 extern void add_(float *a, float *b, float *c); 4 5 int main(int argc, char *argvs) 6 7 float a, b, c; 8 a = 5.0; 9 b = 7.0; 10 add_(&a, &b, &c); 11 12 return 0; 13 3: 声明你要调用的函数,这里注意,是add_,调用的时候用指针,即变量地址,你应该明白了Fortran的调用是改变参数值的。 10:调用fortran函数 编译与执行 #gfortran -o main main.c add.o #./main 5.000000 + 7.000000 = 12.00000 NOTES; if you use the gcc tool, it will generate error #gcc -o main main.c add.o add.o: In function add_: add.f95:(.text+0x4c): undefined reference to _gfortran_st_write add.f95:(.text+0x69): undefined reference to _gfortran_transfer_real add.f95:(.text+0x87): undefined reference to _gfortran_transfer_character add.f95:(.text+0xa4): undefined reference to _gfortran_transfer_real add.f95:(.text+0xc2): undefined reference to _gfortran_transfer_character add.f95:(.text+0xdf): undefined reference to _gfortran_transfer_real add.f95:(.text+0xed): undefined reference to _gfortran_st_write_done collect2: ld returned 1 exit status Some Wrong with your PATH for you gcc library OK! you are clever and has known how call fortran routines in the C progaram. Next part I show you how to call C routines in the Fortran program! 2, Fortran 调用 C 函数 编辑C源码add.c 1 #include 2 3 void add_(float *a, float *b, float *c) 4 5 *c = *a + *b; 6 printf(%f + %f = %fn, *a, *b, *c); 7 Notes The funtion name add_ 编译源代码 # gcc -o add.o -c add.c 编辑fortran 主程序main.f95,编译和执行 1 PROGRAM MAIN 2 implicit none Page 3 real: i, j, k 4 ! 5 ! The first fortran program 6 ! 7 i = 5.0 8 j = 8.0 9 call add(i, j, k) 10 stop 11 end program MAIN NOTE 9 line # gfortran -o main main.f95 add.o (or f95 -o main main.f95 add.o) # ./main 5.000000 + 8.000000 = 13.000000OK. If you reach here, congratulations, you have learned how to call routines between C and fortran!1. 经典文档:/software/cppf77/cppf77.htm /补充几个/fortran_and_cplusplus.html/support/mixing_f77_c_cpp/mixing_f77_c_cpp.html/software/c-with-fortran.html/t/20040319/20/2863500.html例程:Calling Fortran routines from C+Example-1: Calling routines and functionsThe following sample shows how Fortran routines and functions can be called from a C+ program.(1) The C+ file:/ This illustrates how a Fortran routine and function may be/ called from a main program in C+#include extern C void _stdcall FR1(int*,int *); int _stdcall FF1(int *);int main() int n=10,nSq,nCube; FR1(&n,&nSq); cout The square is: nSq endl; nCube=FF1(&n); cout The Cube is: nCube endl; return 0;(2) The Fortran file: SUBROUTINE FR1(N,M)C COMPUTES THE SQUARE OF N, RETURNS IN M M=N*N RETURN ENDC INTEGER FUNCTION FF1(N)C COMPUTES THE CUBE OF N FF1=N*N*N RETURN ENDBack to TopExample-2: Passing C char string to a Fortran routineThe following sample shows how a C char string may be passed from a C+ program to a Fortran routine.(1) The C+ file:/ This illustrates how a Fortran routine may be/ called from a main program in C+, and a char string passed to it#include #include extern C void _stdcall FR1(int *,int *,char *);int main() int n=10,nSq;char szCtest20;strcpy(szCtest,teststring);FR1(&n,&nSq,szCtest);cout The square is: nSq endl; return 0;(2) The Fortran file: SUBROUTINE FR1(N,M,CSTR)INTEGER*4 CSTR(1)C HERE WE RECEIVE THE C CHAR STRING IN AN INTEGER ARRAYC COULD ALSO HAVE USED A BYTE ARRAYM=N*NWRITE(6,20) (CSTR(L),L=1,3) 20 formAT( CSTR=,3A4) WRITE(6,*) DONERETURNENDBack to TopExample-3: Passing arrays to a Fortran routineThe following sample shows how arrays may be passed from a C+ program to a Fortran routine.(1) The C+ file: / Illustrate passing integer and floating point arrays / from C+ to Fortran #include extern C int _stdcall SUMIT(int *,int*); float _stdcall MEAN(float*,int*); int main() int iA=3,5,6,7,2,3,4,5,11,7,iN=10,iSum; float fpA=1.2f,3.f,44.f,2.5f,-1.3f,33.44f,5.f,0.3f,-3.6f,24.1f,fpMean; iSum=SUMIT(iA,&iN); cout The Sum of iA is: iSum endl; fpMean=MEAN(fpA,&iN); cout The Mean of fpA is: fpMean endl; return 0; (2) The Fortran file: INTEGER FUNCTION SUMIT(IA,N) INTEGER IA(1) ISUM=0 DO 50 J=1,N50 ISUM=ISUM+IA(J) SUMIT=ISUM RETURN ENDC REAL FUNCTION MEAN(RA,N) REAL RA(1) SUM=0. DO 50 J=1,N50 SUM=SUM+RA(J) IF(N.GT.0) MEAN=SUM/FLOAT(N) RETURN ENDBack to TopCalling C+ routines from FortranThe following examples work with Microsoft Visual C+ and Compaq Visual Fortran. Your mileage may vary on other systems.Example-1: Calling routines and functionsThe following sample shows how C+ routines and functions can be called from a Fortran program.(1) The Fortran file: INTEGER CR2 N=10 CALL CR1(N,M) WRITE(6,20) N,M20 formAT( The square of,I3, is,I4) K=CR2(N) WRITE(6,30) N,K30 formAT( The cube of,I3, is,I15) CALL EXIT END(2) The C+ files: extern C void _stdcall CR1(int *,int *);int _stdcall CR2(int *); void _stdcall CR1(int *n, int *m) / Compute the square of n, return in mint k;k=*n;*m=k*k;return; int _stdcall CR2(int *n) / Compute the cube of n int m,k;k=*n; m=k*k*k;return m; Back to TopFurther ReadingThese are some other sources of information.Digital Visual Fortran Programmers Guide, esp. the chapter titled Programming with Mixed Languages. This online book is included with all recent versions of the compiler. The book is also available for download in PDF format by clicking here.Mixed-Language Issues (from Microsoft)Also see Microsofts C Calls to Fortran page.Mixed Language Programming using C+ and Fortran 77 by Carsten A. Arnholm has many examples.Mixed Language Programming - Fortran and C by Allan, Chipperfield and Warren-Smith is another good source.FTN95 Mixed Language Programming from the University of Salford.A Comparison of C+, Fortran 90 and Oberon-2 for Scientific Programming by Bernd Msli.Interfacing Fortran and C by Janne Saarela.Mixed Language Programming from Pittsburgh Supercomputing Center.Some examples from DEC:Visual C/C+ Calling Visual Fortran DLL ExampleVisual Fortran Calling Visual C ExampleVisual Basic - Visual Fortran DLL ExampleWill C+ be faster than Fortran? by T.L.Veldhuizen and M.E.Jernigan.Interfacing Absoft Fortran with C.Mixing ANSI-C w
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 60794-1-110:2025 FR Optical fibre cables - Part 1-110: Generic specification - Basic optical cable test procedures - Mechanical tests methods - Kink,Method E10
- 部编人教版小学6六年级语文下册教案
- 重庆知识教育培训课件
- 暑假培优练:实验综合练 -2025高一物理暑假专项提升(人教版)
- 外研版八年级英语上册Module1单元测试试卷-含答案03
- 统编版语文八年级下册第四单元练习 (含答案)
- 重大危险源管控
- 老年人身体变化课件
- 《中外语言对比》课程简介与教学大纲
- CN115359845B 一种融合单细胞转录组的空间转录组生物组织亚结构解析方法(广东工业大学)
- 小学科学新教科版三年级上册全册教案(2025秋新版)
- 苏教版2025-2026秋三年级数学上册教学计划及课时安排
- 【里斯】年轻一代新能源汽车消费洞察与预测 -新物种 新理念 新趋势(2024-2025)
- DB32T3916-2020建筑地基基础检测规程
- 新苏教版六年级上册《科学》全一册全部课件(含19课时)
- 二年级上册生命.生态.安全 全册教案
- (完整版)英语能力B级考试课件
- (中英)订购单-Purchase-Order
- 框架结构(课件)
- 有机化学第五章 脂环烃
- 铁路货物装载加固规则
评论
0/150
提交评论