IntelVisualFortran应用程序开发_第1页
IntelVisualFortran应用程序开发_第2页
IntelVisualFortran应用程序开发_第3页
IntelVisualFortran应用程序开发_第4页
IntelVisualFortran应用程序开发_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 #IntelVisualFortran应用程序开发第10章IntelFortran与VisualC+ HYPERLINK file:/Basic.NET/Basic.NET的混合编程每种编程语育都冇其特有的优势和局限性,将儿种语言混合起来使用即混合编程,则可充分发挥各种语言的优势.弥补它们在某些功能上的不足。这样,既利用了现有程序资源,又加快了应用程序的开发。由于开发环境发生了很大的变化IntelVisualFortran9.0与VisualC+/Basic.NET的混合编程和CompaqVisualFortran6.x与VisualC+/Basic6.0的混合编程在有些方面是不同的。本章主

2、要内容:混合编程概述协调调用约定协调命名约定传递数据匹配数据类型IntelFortran/VisualC+.NET的编译和钱接10.1混合编程概述10.1.1混合编程的优势混合(语言)编程.指源程序由两种或两种以上语言编写而成,它涉及一种语言编写的程序对另一种语言编写的例程实施调用的问题。混合编程允许:调用由另一种语育编写的现有程序代码;使用在特定语言环境下难以实现的算法; IntelVisualFortran应用程序开发获得处理速度方而的优势;Fortran/VisualBasic:利用VisualBasic高效地实现用户界面.Fortran做所有的计算工作,尤梵是浮点计算以充分发挥两者的优

3、势;Eortran/C(或C+):可以相互调用以充分利用两者现有的程序资源。10.1.2混合编程的前提条件Win32系统下的混合编秤不同于Winl6系统下的但在许多方面更容易实现。利MicrosoftVisualStudio开发环境实现混合编程要求开发工具拥有相同的版本;MicrosoftVisualStudio.NET解决方案资源管理器中的一个工程只能使用一种语言,毎一种语言必须包含在自己的工程中。Win32系统下的IntelFortran.VisualC/C+、InteiC+和VisualBasic之间的混合编程之所以可行,足因为它们实现例程(子程序和国数的统称)的方式大致相同:函数有返冋

4、值,子程序没有返回值。表lo-i列出r这些语言所对应的例程。例如.c语言主函数可以调用一个void类型的函数而该函数实际由Fortran子程序(subroutine)实现衰101Fortran与C/O+、VisualBasic对应的例程两数声程序FortranFUNCTIONSUBROUTINEC/C+function(void)functionVisualBasicFunctionSub10.1.3调用约定尽管I:述语肓在实现例程的方式上大致相同但它们都遵循各自的规则来命名II标变址和例程、管理堆栈及进行参数传递等;.这一规则就称为调用约定。调用约定具体包括以下几个方血的内容。堆栈管理被调用

5、的例程能否接收町选参数?调用程序和被调用例程哪个负责清理调用后的堆栈? #IntelVisualFortran应用程序开发命名约定编译产生的口标实体(指数据和例程)名是统一转换成小写、大写.还尼保持大小写混合?目标例程名是否有前后缀?参数传递协议参数传递采取值传递还是引用传递?实参和煖参的数据类型和数据结构是否对应?在单一语育编程中.无须关注调用约定的问题;但在混合编程中,必须全面、一致地协调两种语肓所便用的调用约定,否则会导致混合编程失败.或出现不确定的结果10.1.4.NET下的混合编程实现方式在.NET下进行上述语言间的混合编程,可以用IntelFortran构造主程序.并调用其他语育编

6、写的例程;或者.用其他语苔构造主程序,调用IntelFortran例程(外部例程)被调用的例程可存放在H标对彖文件(.OBJ)、静态库(丄IB)和动态链接库(.DLL)中,如表102所示。袁10-2Fortran与C+/VisualBasic混合编程方式方式被调用例程调用程序优点峡点冃标对彖文件(OBJ)、静态库(丄IB)IntelFortranIntelC+VisualC卄(非托管)IntelFortranIntelC+VisualC+(非托管)貝冇较高的执行性能.IntelFortran使用起来较为方便静态库必须和其他语育支持库保持兼容动态链接库(.DLL)IntelFortranInte

7、lC+VisualC+(非托管)VisualBasic(非托管)IntelFortranIntelC+VisualC+VisualBasic具有本机代码性能使用语言广泛.不“在语耳支持库冲突问题在某些讲肓环境中,动态链接库使用起来絞为烦琐、闲难NET框架貝仃两个主要组件:公共语言运行库和.NET框架类库。其中,公共语用运行库是.NETFramework的基础.它作为一个在执行时管理代码的代理.捉供了诸如内存管理、线程管理和远程处理的核心服务,并强制实施严格的类型安全以及可确保安全性和可靠性的其他形式的代码准确性。以公共语言运行库为冃标的代码称为托符代码,而不以运行库为目标的代码称为非托管代码。

8、显然.托管代码运行在公共语言运行库下.且独立于特定的系统; IntelVisualFortran应用程序开发而非托管代码是本机代码,它依赖于待定的系统。IntelFortran创建和使用动态链接库已在第9章进行了介绍,而基于目标对象文件的方式主要是Winl6下的混合编程方式。故此,本章后续部分主要探讨在.NET集成开发环境(IDE)下,基尸静态库的IntelFortran与VisualC+NET(非托管)及基于动态链接库的IntelFortran与VisualBasic.NET(非托管)的混合编程问题10.2协调调用约定阔用约定决定了如何调用例程、如何传递参数及如何命名目标例稈。在单一语肓编程

9、中,使用默认的调用约定,并通过头文件或包含接【的Fortran模块在调用程序与被调用例程间保持一致性,所以其调用约定总是正确的。在混合语育编程中,各种语言不能共享相同的头文件,假如它们使用不同的凋用约定,那么在编译和链接时难以发现错溟,但在运行时必然卢生错谋的调用。错误的调用引发不确定的结果.或产生严重错谋,并导致内存/堆栈岀现“腐烂”。因此,必须使调用约定在不同的语言间协商一致。具体讲,调用约定从以下5个方面对混合编程产生影响:凋用程序利用调用约定确定向被调用例程传递参数的顺序,而被调用例程利用调用约定确定接收参数的顺序Fortran.VisualC/C+及VisualBasic都是按从左到

10、右的顺序传递参数。调用程序和被调用例程使用调用约定来确定它们中的哪一个负责清理调用后的堆栈空间。调用程序和被调用例程使用调用约定来传递可选参数。调用程序和被调用例程使用调用约定来确定参数传递采取值传递还是引用传递。调用程序和被调用例程使用调用约定来建立目标实体命名规则。10.2.1属性编译指令和调用约定在IntelFortran中,可以通过规定不同的屈性(ATTRIBUTES)编译指令,来选择使用不同的调用约定其中,C、STDCALL、REFERENCE.VALUE和VARYING指令属性都对调用约定产生影响。对整个例程可规定C、STDCALL、REFERENCE和VARYING属性;对参数可

11、单独规定VALUE和REFERENCE传递属性。 #IntelVisualFortran应用程序开发笫*10章IntelFortran与VisualC*/Basic.NET的涙合编程 默认悄况下IntelFortran以引用方式传递所有参数(隐含长度字符串参数除外)。假如规定C或STDCALL调用约定选项那么IntelFortran以值方式传递所有参数(数组参数除外)。在调用约定选项C和STDCALL之外,还可单独对参数规定VALUE和REFERENCE传递展性,以强制参数分别以值方式和引用方式传递,此时,C和STDCALL调用约定选项对参数传递的影响被覆盖。而数组参数只能以引用方式传递.且传

12、递的是数组首地址。【例10-1在1A-32系统下IntelFortran调用混合大小写命名的C函数:位于静态库中的C语言函数(c)为:includeexternvoidMy_Sub(inti)printfC=%d”,i);C语育编译器使用缺省调用约定(_cdecl),其参数传递方式采取值传递,产生的口标例程名(_My_Sub)保持编译前的大小写混合形式,并添加一前导下画线。调用该函数的IntelFortran控制台程序(.20)为:programEx_limplicitnoneINTERFACESUBROUTINEMY_SUB(I)!DEC$ATTRIBUTESC,ALIAS:_My-Sub:

13、MY_SUBINTEGERIENDSUBROUTINEMY_SUBENDINTERFACEcallmy_sub(5)endprogramEx_l IntelVisualFortran应用程序开发笫*10章IntelFortran与VisualC*/Basic.NET的涙合编程 Fortran子稈序与C语言void函数相对应。在建立外部例程接I块时声明MY_SUB貝有C约泄属性,使梵与C语育的缺省调用约定及参数传递保持一致;InFortran的ALIAS属性可以利其他的属性选项结合使用,以使产生的目标例程名呈现待定的形式.这里,ALIAS属性使MY_SUB产生的冃标例程名限定为_My.Sub.恰

14、好与C语言编译产生的目标函数名相同。在ltanium系统下,目标例程名没冇前导下画线.故相应的属性声明应为:!DEC$ATTRIBUTESC,ALIAS:,My-Sub,:MY_SUB要便编译的代码既能运行在IA32乂能运行在Itanium系统平台上.可以使用条件编译指令;也可使用预定义的预处理器指令宏(如JvlX86、_MA64);还可便用DECORATE编译选项结合ALIAS别名屈性,便产生的口标例稈名能依据特定的系统添加正确的前缀和后缀。例如,上列屈性编译指令可改写为:!DEC$ATTRIBUTESC,DECORATE,ALIAS:MySub:MY_SUB表103.表104及表10-5分

15、别列岀了IntelFortran各种屈性编译指令下的参数传递、冃标例程命名及堆栈清理悄况.各表中的术语解释见表10-6o在IntelFortran中.除了规定调用约定屈性编译指令外,还可通过规定/iface编译选项来建立特定的调用规则,如衷107所示。从中可以看出/iface编译选项对参数的传递n标例程命名、堆栈清理等均产生影响10.2.2堆栈清理及可选参数传递Fortran与C/C+的例程调用均通过堆栈进行:调用程序在传递参数时.将例程地址、例程参数压入堆栈;被调用例程在接收参数时,依次将例程参数和例程地址从堆栈中弹出。进栈时,例稈参数从左到右;出栈时,例程参数从右到左,即先进栈的参数后出栈

16、。在IntelFortran的缺省约定和C约定下,当执行流程由被调用例程返回时.调用程序(Caller)负责清理堆栈(表105)这便得调用程序的冃标代码稍大一些,因为在毎一例程调用点处都要插入直建堆栈的代码;在STDCALL约定下,被调用例程(Callee)负责控制堆栈,重建堆栈的代码驻留在被调用例程内,貝只出现一次O正因为在C约定下由调用程序消理堆栈.不管传递多少个参数.总能保持相对于框架指针的同一个地址.所以、调用稈岸知道冇多少参数被传递、这些参数占多少字节、它们都驻留在堆栈的什么位置等信息,它可以不连续地传递参数(即跳过某些参数)因此C约定可以传递可变数址的参数,即可选参数。衰103In

17、telFortran各种岡性编译指令下的参数传递裁数DefaultcSTDCALLC,REFERENCEREFERENCEScalarReferenceValueValueReferenceReferenceScalarvalueValueValueValueValueValueScalarrefcrcnccIReferenceReferenceReferenceReferenceReferenceSiringReference,Lcn:End/Lcn:MixcdString(l:l)String(l:l)Reference,Len:End/Len:MixcdReference,Lcn:End

18、/Len:MixcdStringvalueErrorString(I:I)String(1:1)String(l:l)String(1:1)String(reference)Reference,NoLcn/Len:MixcdReferenceNoLenReference,NoLenReference.NoLenReference.NoLenArrayReferenceReferenceReferenceReferenceReferenceArrayvalueErrorErrorErrorErrorErrorArrayreferenceReferenceReferenceReferenceRef

19、erenceReferenceDerivedTypeReferenceValue.SizedependentValue.SizedependentReferenceReferenceDerivedTypevalueValue,SizedependentValue,SizedependentValue.SizedependentValue,SizedependentValue.SizedependentDerivedTypereferenceReferenceReferenceReferenceReferenceReferenceF90PointerDescriptorDescriptorDes

20、criptorDescriptorDescriptorF90PointervalueErrorErrorErrorErrorErrorF90PointerreferenceDescriptorDescriptorDescriptorDescriptorDescriptor*10-4IntelFortran各种嵐性编译指令下的目标例程命名例程名DefaultCSTDCALLC.REFERENCESTDCALL.REFERENCESuffixnonenonen(1A-32)nonen(IA-32)CaseUpperCaseLowerCaseLowerCaseLowerCaseLowerCase10

21、-5IntelFortran各种属性编译指令下的堆栈滴理项目DefaultCSTDCALLC,REFERENCESTDCALL,REFERENCE堆栈清理CallerCallerCalleeCallerCallee表10-6衰10-3.表10-4及表10-5中的术语解释术语|描述(value)声明参数具有VALUE属性reference)声明参数貝有REFERENCE属性Value值传递.即参数值被压入堆栈Reference引用传递在1A-32系统中.4字节的参数地址被压入堆栈;在IntelEM64T和Itanium系统中.8字节的参数地址被爪入堆栈Len:End/Lcn:Mixed针对某些字

22、符串參数Len:End对应/iface:nomixedstrlenarg编译选项.字符申的长度值在所冇的其他参数后压入堆栈(硕杯设唾);Len:Mixcd则对应/ifacc:mixedstrlenarg编译选项字符串的长度值紧接肴字符串的起始地址压入堆祕NoLen/Len:Mixcd针对某些字符申参数.NoLen对应/iface:nomixcdstrlenarg编译选项.字符串的长度不传入被凋用例程(缺省设就匚Lcn:Mixed則对应/iface:mixed_str_len.arg编译选项字符串的长度值紧接若字符串的起始地址压入堆栈NoLen针对字符串参数字符串的长度不传人被调用例程Strin

23、g(l:l)针对字符申参数其首字符通过ICHAR(string(l:l)转换为1NTEGER(4),然后被压入堆栈Error产生编译错误Descriptor在IA-32系统下.传递数组描述子的4字节地址;在IntelEM64T和Itanium系统下.传递数组描述子的8字节地址n在IA-32系统下n代我参数表所占据的字节数(十进制)Sizedependent在IA-32系统下,由值属性规定的派生类型:14字节的参数按值方式传递;5-8字节的参数放在两个寄存器(对应两个参数)中并按值方式传递;多于8字节的参数按引用方式传递一个临时存储地址.该“储地址与待定的数据类型相关联UpperCase目标例程

24、全部为大写LowerCase冃标例程全部为小写Callee被凋用例程负责清理调用后的堆找Caller调用程序负责清理调用后的堆栈 IntelVisualFortran应用程序开发第10章IntelFortran与VisualC+/Basic.NET的混合编程 #衰10-7/iface编译选项对调用约定的影响编译选项参数传递方式9n后缀(IA-32)堆栈清理可选鑫数传递/ifaccxrcfByreferenceNoCallerYes/ifacc:stdrcfByreferenceYesCalleeNo/iface:defaultByreferenceNoCallerYes/iface:CByva

25、lueNoCallerYes/iface:STDCALLByvalueYesCalleeNo/iface:CVFByreferenceYesCalleeNo在IntelFortran中,通过在C约定之外声明外部例程拥有VARYING属性,可以调用具冇可选参数的外部例程。VARYING选项,可使Fortran在执行例程调用时放弄匹配参数个数的要求;若要调用具有可选参数的Fortran90系统例程,则无须添加该选项。10.2.3匹配IntelFortran与C/C+的调用约定IntelFortran调用约泄属性与C/C+调用约泄的匹配情况见表108。VisualC/C+IntelFortran_c

26、dccl(dcfault)C(default)_stdcallSTDCALL表108IntelFortran调用约定屐性与C/C+*调用约定的匹配注:WindowsAPI使用的用约定U&CVF的缺省约定齣为STDCALL在默认悄况下,VisualC+开发环境便用缺省调用约定(_cdecl)来调用函数。如果C语言程序要调用采用STDCALL约定的Fortran外部例程.那么可以在外部函数原型声明中直接添加_stdcall关键字。该调用约定既址WindowsAPI便用的调用约定也是CVF使用的缺省约定。【例10-2在IA-32系统下,C程序调用具有_stdcall约定属性的Fortran函数:位于

27、静态库中的Fortran国数为:FUNCTIONMYJFUN(n)IMPLICITNONE!DEC$ATTRIBUTESSTDCALL:MY_FUNINTEGERMY_FUN,n #IntelVisualFortran应用程序开发第10章IntelFortran与VisualC+/Basic.NET的混合编程 MYFUN-nnENDFUNCTIONMY_FUN声明Fortran函数MY_FUN具有STDCALL约定属性.在该约定下目标例程名被转换成小写.参数传递采取值传递。相应的c语言控制台程序为:#includeexternint_stdcallmyfun(intn);voidmain(vo

28、id)printfVmy_fun(5)=%diT,my_fun(5);C语言主函数只能使用缺省调用约定(_cdecl),但它调用的外部函数却可以声明使用_stdcall调用约定。C语言中的调用约定对参数传递(以值方式传递)没有影响;目标函数名总保持编译前的形式,这里外部函数名采用小写,恰好与Fortran目标函数名(_my_fun4)致。如果IntelFortran程序要调用C语言函数,不必修改C语言程序使用的缺省约定(_cdecl),而是直接在IntelFortran外部例程接口中声明外部例程具有C约定屈性,这样.既使调用约定保持匹配.又使参数传递保持一致,如例101所示。10.3协调命名约

29、定在IntelFortran中,C和STDCALL约定属性不仅规定了调用约定.同时也规定了命名约定。调用约定建立了参数传递和存储的规则,而命名约定则建立了目标对象文件(.OBJ)中标识符的命名规则。这里的标识符指在调用程序与被调用例程间共 IntelVisualFortran应用程序开发第10章IntelFortran与VisualC+/Basic.NET的混合编程 #亨的实体名.如外部例程名、模块名等.它们标识了一个特定的内存位置(地址),在调用程序与被调用例程中必须保持相同。由于C语言区分字母的大小写(即大小写敏感).Fortran不加以区分C+乂添加了待定的修饰,导致编译后的目标标识符发

30、生改变,在上述语言的混合编程中如果命名约定不一致,将在链接目标对彖文件时产生“unresolvedextemaP链接错误。为避免链接失败.必须协调Fortran与C/C+的命名约定,以使产生的目标实体名保持致O1031IntelFortran和C/C+的命名约定Fortran和C/C+的命名约定列于表10-9o从中可以看出,C/C+的目标例程名保持编译前的大小写混合形式而Fortran的目标例程名统一被转换成大写(缺省约定)或小写(C和STDCALL约定)。不过,IntelFortran提供了ALIAS属性编译指令.可用來消除C/CM与Fortran在目标例程命名上出现的分歧.使产生的目标例程

31、名呈现大小写混合形式,从而覆盖IntelFortran的调用约定所建立的命名规则。衰10-9IntelFortran和C/C+的命名约定WW调用约定(属性)目标例程名目标例程名大.小写Fortran!DEC$ATTRIBUTESCnameAlllowercaseFortran!DEC$ATTRIBUTESSTDCALL_namcnAlllowercaseFortrandefault_nameAlluppercaseCcdecl(default)nameMixedcasepreservedC_stdcall_namcnMixedcasepreservedC+Default_namedecorat

32、ionMixedcasepreserved注:&中H标例程名的输詁卜*线和n(n播琴数列设所占字D散以卜逬制丧示)只适用TIA-32系统;4:Itanium系fit下Kt不仔在前导下线电不冇在后缀nC+与C使用相同的调用约定和参数传递协议,但它们便用的命名约定不同。当位于.cpp文件中的C+源代码被编译成目标对象文件时,C+编译器在冃标例程名上添加J待定的修饰.导致和其他语言的目标文件链接失败,通过规定C+外部函数真冇extern9”链接选项,可消除C+的命名修饰.从而使C+目标文件能够与Fortran目标文件共享数据和例程。C+程序若要调用Fortran例程.可以像C语言程序那样声明外部隨数

33、.但须规 #IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 定C”链接选项。例如:externHCHintFACT(intn);具中,FACT是具有缺省约定属性的Fortran外部函数。当从C+中调用其他语言编写的外部例程,或从其他语言中调用C+函数时,extern”C链接选项可用来调整C+的命名约定,但该链接选项只能在C+内部使用。假如其他语言要调用C+函数,而在C+内又不规定extern“C”链接选项,那么只能设法使其他语言编译器产生包含C+特定修饰的目标例程名。这-做法只能作为最后的解决方法,因为不能保证C

34、+不同版本的编译器会使用相同的命名修饰方案。extern链接选项的使用存在下列限制:(】)不能声明类的成员函数具有extern“C”选项;(2)只能规定重载更数的一个实例具有extern“C”链接选项,重载函数的其他实例须使用C+链接。10.3.2协调口标实体名的大、小写大写假如C/C+调用IntelFortran例程,而IntelFortran采用缺省约定,且其代码不能被重新编译,那么在其编译产生的目标对彖文件中,目标例稈名统一被转换成大写。与之相适应.C/C+要用大写命名外部函数.【例10-3在IA-32系统下,C+调用使用缺省约定的IntelFortran函数。位于静态库中的IntelF

35、ortran国数为:FUNCTIONSquare(n)IMPLICITNONEREAL(8):Square,nSquare=n*nENDFUNCTION默认悄况下IntelFortran使用C调用约定,但目标例程名统一被转换成大写 IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 #(SQUARE).参数传递采取引用传递(即地址传递)。调用该函数的C+控制台程序为:#includeusingnamespacestd;extern9”doubleSQUARE(double&n);voidmain(intargctch

36、ar*argv(J)doublei=5.0;coutHSquare(5.0)=uSQUARE(i)endl;其中,extern“C”链接选项旨在消除C+产生的命名修饰;通常.C/C+参数传递采取值传递,若要进行地址传递,C+除了像C语言那样使用指针参数外.还可便用引用参数,如该例所示。小写假如Fortran采用C或STDCALL约定,其冃标外部例程名统一被转换成小写.那么C/C+除使用与Fortran对应的缺省约定(_cdecl)或stdcall约定声明外部函数原型外,还须便用小写命名外部噸数(例I0-2)o下列Fortran函数使用C约定:REALFUNCTIONFFARCTAN(Angle

37、)!DEC$ATTRIBUTESC:FFARCTANREAL(4):AngleC约定下,Fortran以值方式传递参数(数组参数除外),与C/C+的参数传递方式一致。在这种情况下,相应的C/C+函数原型声明分别为:externfloatffarctan(floatangle);extcmMCHfloatffarctan(floatangle);在IA-32和Itanium系统下.编译产生的目标例程名分别为ffarctan和ffarctan。大小写混合假如C/C+的外部函数名采取大小写混合形式,在Fortran中若要保持一样的形 #IntelVisualFortran应用程序开发第10*Inte

38、lFortran与VisualC*/Basic.NET的混合编程 式.必须采用ALIASJgn来限定产生的目标例程名。详见例lO-lo10.3.3IntelFortran模块命名规则马英他外部实体(数据和例程)的命名规则不同.Fortran模块目标实体命名为:_MODULENAME_mpENTITYstacksize其中,MODULENAMEM模块名.缺省悄况下被统一转换成大写;ENTITY是模块中的数据或例程名.缺省情况下也转换成大写;_mp_是模块名与模块实体名间的分隔符,总采取小写形式。例如下列模块:MODULEmymodINTEGERaCONTAINSSUBROUTINEb(j)INT

39、EGERjENDSUBROUTINEENDMODULE该模块在IA-32系统的目标对象文件(.OBJ)中其a、b实体命名为:_MYMOD_mp_A_MYMOD_mp_B在Itanium系统中则为:MYMOD_mp_AMYMOD_mp_B在不同的属性编译指令下,上列模块例程b的目标模块例程命名悄况列于表10-10.从中可见.目标模块实体名中的模块名总保持大写,而和屈性选项(ALIAS属性除外)无关。表10-10不同尺性编译指令下的模块例程命名属性选项IA-32系统中的目标模块例程Itanium系统中的目标模块例程NoneMYMOD_mp_BMYMODmp_BC_MYMOD_mp_bMYMODmp

40、_bSTDCALL-MYMOD_mp_b4MYMOD_mp_bALIAS故盖其他选项的命名彫响便II标模块例程保持alias选项规定的形式覆盖氏他选项的命名影响.使目标模块例程保持alias选项规定的形式 IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 #当IntelFortran与C/C+共享模块数据和例程时,往往使用ALIAS属性选项.使冃标模块实体名呈现较为简单的形式。10.4传递数据在IntelFortran与C/C+间传递数据的方式有:使用例稈参数、模块和外部变10.4.1例程参数通过例程参数在Inte

41、lFortran和C/C+间共享数据,是常用的数据传递方式,也是IntelFortran与VisualBasic间共享数据的唯一方式。参数传递方式共有两种:值传递,即传递参数的值。引用传递或地址传递,即传递参数的地址在IA-32系统中,Fortran与C/C+的参数地址占4个字节;而在IntelEM64T和Itanium系统中参数地址占8个字节。Fortran的参数传递方式取决于调用约定。在缺省约定下,IntelFortran以引用方式传递所有参数(隐含长度的字符串参数除外);假如规定例程具有C或STDCALL约定属性,那么IntelFortran以值方式传递所有参数(数组参数除外);假如规定

42、例程具有REFERENCE属性以及C/STDCALL约定届性则Fortran以引用方式传递所有参数。建立参数传递规则,除通过规定上述例程属性外,还可对参数规定VALUE和REFERENCE属性使参数分别以值方式和引用方式传递。若例程属性和参数属性同时存在,则参数传递最终由参数屈性(VALUE和REFERENCE)决定。例如.声明下列IntelFortran例程原型:SUBROUTINETESTPROC(VALPARM,REFPARM)!DEC$ATTRIBUTESVALUE:VALPARM!DEC$ATTRIBUTESREFERENCE:REFPARMINTEGERVALPARMINTEGER

43、REFPARMENDSUBROUTINE此处,例程TESTPROC采用缺省约定,在该约定下参数以引用方式传递;但VALUE和REFERENCE参数属性使VALPARM和REFPARM最终以值方式和引用方式传 #IntelVisualFortran应用程序开发 IntelVisualFortran应用程序开发递。尽管这里规定REFPARM的REFERENCE参数属性不是必须的.但显式规定参数的传递方式是混合编程的一个好习惯。C/C+以值方式传递除数组外的所有参数.而数组参数以引用方式传递,且传递的是数组首地址,不像IntelFortran.C/C+无法通过调用约定指令来规定参数的传递要以引用方式

44、传递非数组参数,C语言只能使用指针参数;要以值方式传递C数组,只能将数组作为结构体的成员进行传递。例如,声明上述IntelFortran例程的C蘋数原型为:externvoidTESTPROC(intValPRefParm);表10-11列出了IntelFortran与C/C+的参数传递悄况。表10-11IntelFortran与C/C*的参数传递语言约定隅性参数类型引用传递值传递DefaultScalarsandderivedtypesDefaultVALUEoptionFortranC/STDCALLScalarsandderivedtypesREFERENCEoptionDefaultD

45、efaultArraysDefaultNoC/STDCALLArraysDefaultNoNon-arraysPointerargument_nameDefaultC/C+ArraysDefaultStructtypearrayname注:&叩不包存Fortran90/95针忿数和字符小参数10.4.2模块C/C+访问模块数据和例程C/C+nr以玄接访问IntelFortran模块中的数据和例程,因此模块成为IntelFortran与C/C+间交换批圮数据的最简单方式。【例10-4学生派生类熨或结构体由学号和成绩构成要求找出戢高分的学生,并算出该班学生的平均分。我们设计一个IntelFortr

46、an模块.当中包含一模块例程(负数)和一模块变量(代表平均分).C+主程序将一个班级的学生成绩作为实参传入模块函数,该函数返冋最高分的学生并将算得的平均成绩存入模块变虽供O+访问。下列为IntelFortran模块: IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 #MODULEExampIMPLICITNONEREAL:Aver!DEC$ATTRIBUTESALIASAver1:AverTYPEStudentSEQUENCEINTEGERNREALMarkENDTYPEStudent!DEC$ATTRIBUTE

47、SALIASrStudcnt1:TYPEStudentCONTAINSFUNCTIONFindMax(Stud,M)!DEC$ATTRIBUTESC,ALIASJFindMax:FindMaxINTEGERMTYPE(Student)Stud(M),FINDMAXINTEGER:I,J=0REAL:T=0.0,S=0.0DO1=ltM1F(T=Stud(I)%Mark)THENJ=Stud(I)%NT=Stud(I)%MarkENDIFENDDOFINDMAX%N=JFINDMAX%Mark=TDOI=1,MS=S+Stud(I).MarkENDDOAver=S/MENDFUNCTIONEND

48、MODULEExamp #IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 为了使目标模块实体名呈现简单形式,模块中用ALIAS屈性限定编译产生的目标实体名,尤其是派生类型名(注意:这里采取的特殊格式);模块丙数FindMax采用了C约定,使其参数采取值传递,以便与C+的参数传递方式保持一致。访问上列模块的C+控制台程序(CPP)为:#includeextern”CfloatAver;externHCMstructStudentintN;floatMark;#defineSTUstructStudentextern

49、,rCMSTUFindMax(STUsJntn);voidmain(intargc,char*argv)STUm,s(3=1001,70,l002,80,1003,90;m=FindMax(s,3);printfT%d:%fn”,mN,mMark);printf(M%fnH,Aver);C+将Fortran模块实体作为苴外部实体看待,Fortran中的派生类型与C+的结构体相对应。需要注意的是,该示例由C+来链接,而在被调用的IntelFortran例程中又使用了派生类型和数组参数.须将IntelFortran的libifcoremd.lib运行库链接到执行文件中。C/C+函数并入模块通过在I

50、ntelFortran模块中建立例程接口块,町以将C/C+函数作为模块例程使用 IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 #例10-5将求平方根的C+噸数转换为IntelFortran模块例程。C+函数(cpp)为:includeexternrCnvoidcsqrt(floata,floatb,float&c)c=(float)sqrt(a*a+b*b);在C+中,用简便的引用参数(c)代替指针参数,其实质都是地址传递使用模块的InlelFortran控制台程序为:MODULECprocIMPLICITNO

51、NEINTERFACESUBROUTINEC_Sqrt(a,b,res)!DEC$ATTRIBUTESC:C_Sqrt!DEC$ATTRIBUTESREFERENCE:resREALa,b,resENDSUBROUTINEENDINTERFACEENDMODULEPROGRAMEx_5USECprocIMPLICITNONEREALXCALLCSqrt(3.0,4.0,X)PRINT化XENDPROGRAM #IntelVisualFortran应用程序开发第10*IntelFortran与VisualC*/Basic.NET的混合编程 这里,接门块的作用类似于C+中的头文件:声明例程原型,貞

52、正的例程实现体由C/C+给出。在接口块中规定了和C+缺省约定(_cdecl)相匹配的C约定,目标例程名统一被转换成小写,参数传递采取值传递;REFERENCE属性使res参数最终采取引用传递。10.4.3外部变量外部变位包括Fortran共用区、C/C+结构体及全局(外部)变id,所有这些变IS在声明它们的单元外部可以访问。全局变Fortran与C/C+共享全局变鈕时,在一种语言中声明为全局的(包括Fortran共用区),而在另一种语肓中则作为外部变量访问。例10-6】ln(clFortran访问C+中的全局变鼠整型数组。位于静态库中的C+文件(.CPP)为:externHCHintIdata

53、3=1,2,3;C+文件只包含一整型数组并进行了初始化。C+的命名修饰不只是针对函数.对全局变戢也产生影响,故此使用了externC”链接选项声明全岗变量。访问C+全局变呈的IntelFortran控制台程序为:programEx6implicitnone!DEC$ATTRIBUTESEXTERN,ALIAS:”dala”:idataINTEGERidata(3)PRINT化idataendprogramEx_6 IntelVisualFortran应用程序开发第10章IntelFortran与VisualC*/Basic.NET的混合编程 #此处.除用EXTERN(EXTERN通知编译歸:该

54、变g:实际是在另一个源文件中声明的)向明与C+对应的全局变址外还使用了ALIAS屈性限定产生的冃标变址名使其与C+产生的目标变呈名保持一致。反之,C/C+也可以访问Fortran中声明的全局变呈(共用区)。【例10-7C语育访问IntelFortran中的单变呈共用区。位于静态库中的IntelFortran数据块为:blockdataimplicitnonerealPlcommon/Pl/PldataPI/10.0/end变量及存放变址的共用区取相同的名称Pio访问上述全局变屋PI的C语言(C)控制台程序为:#includevoidmain(intargc,char*argv)externfl

55、oatPI;printf(uPl=%fPI);这里,C语言声明的外部变屋实际为Fortran共用区名.而不是共用区中的变量名。因此.C/C+无法访问Fortran无名共用区中的变童。共用区和结构体在例107中.Fortran共用区和变量取相同的名称.可以和C语肓中的外部变 #IntelVisualFortran应用程序开发第10章IntelFortran与VisualC*/Basic.NET的混合编程 斌相对应。浪然,若共用区中包含多个变呈,无法使多个变就都取共用区的名称。在这种悄况下,就需要利用结构体与共用区交换数据。为了实现结构体与共用区间的数抿交换.必须考虑两者在存储成员变量方式上的差别

56、Fortran以紧凑格式存储共用区变显:.并遵循下列规则:诸如BYTE、INTEGER(l)、LOGlCAL(l)和CHARACTER类型的单个成员变员紧接着前一个成员变址或数组的地址存储。其他类型的单个成员变坦,紧接君前一个成员变就或数组的偶数地址存储。除CHARACTER类型外的数组成员.紧接着前一个成员变応或数组的偶数地址存储;CHARACTER类型的数组成员,总处紧接着前一个成员变绘或数组的地址存储。(4)所有的共用区从4字节对齐的地址开始存储。正因为共用区存在上述封装规则,在C结构体与Fortran共用区交换数据时,必须确保结构体成员与共用区成员的对齐方式是一致的。可以考虑在这两种语

57、言中只便用4字节和8字节数据类型;或者在C程序中便用pragmapack(2)预处理指令,来硬性规定结构体采取共用区的成员对齐方式。共用区与结构体的数据交换存在两种方式:一是直接访问,二是传递共用区地址。直接访问共用区和结构体通过在C程序中声明与共用区对应的外部结构体,并保证两者成员的对齐方式是一致的.就可以在C程序中直接访问共用区。【例10-8C程序通过结构体直接访问IntelFortran共用区中的多个成员变址。位于静态库中的IntelFortran数据块单元为:blockdataimplicitnone!DEC$ATTRIBUTESALlASrReally*:ReallyREAL(4)x

58、,y,z(3)REAL(8)ydblCOMMON/Really/x,y,z,ydbldatax.y,z,ydbl门.0,2.0,10.0,20.0,/end IntelVisualFortran应用程序开发第10章IntelFortran与VisualC*/Basic.NET的混合编程 #这里对数据块中的共用区规定了ALIAS届性.以便和C程序结构体变呈的混合大小写目标名保持一致。值得注意的是,共用区中的成员数组只规定数组名,而不能采取声明时的形式。访问上述共用区的C语育控制台程序为:#pragmapack(2)externstructfloatx、y,z3;doubleydbl;Really

59、;#pragmapack()#includevoidmain(void)printf(nx=%f,y=%fn*Really.x,Really.y);printKMz0=%Czl=%f,z2=%fnReally.z0,Really.z1,Really.z2J);printf(Mydbl=Rcally.ydbl);C程序通过规定pragmapack预处理指令,使Really外部结构体采取和IntelFortran共用区一致的对齐方式;为了恢复先前的结构体封装模式,在结构体定义的后面必须添加pragmapack()预处理指令。另外,这里的Really是结构体变星名,而不是结构体类型名。只要保证结构体

60、和共用区采取相同的对齐方式.就既能通过结构体从C语肓中访问共用区,也能通过共用区从IntelFortran中访问结构体,2)共用区(结构体)作为引用参数传递如果共用区(结构体)作为值参数传递,那么需要拷贝其每一成员的值,效率比 #IntelVisualFortran应用程序开发 IntelVisualFortran应用程序开发较低下;但作为引用参数传递,则只需传递其4字节(在IA-32系统下)的地址。如同数组中第一个元素的地址为数组首地址一样,共用区(结构体)中第一个成员的地址即代表其首地址。这样.就可以在C函数中声明结构体指针参数;而在对应的Fortran例程中声明和共用区第一个成员同类型的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论