简体   繁体   English

使用Fortran 77子程序作为独立程序,从C ++调用

[英]Using Fortran 77 subprogram as stand-alone, calling from C++

So I've been avoiding Fortran like the plague, but finally my time has come... I need to take part of someone else's Fortran code (let's call it program A) and do two things with it: 因此,我一直像瘟疫一样避开Fortran,但最终我的时机到了……我需要参加别人的Fortran代码(我们称之为程序A),并用它做两件事:

(1) Merge it with a third person's Fortran code (let's call it program B) so that B can call A (1)将其与第三方的Fortran代码合并(我们将其称为程序B),以便B可以调用A

(2) Merge it with my C++ code (program C) so that C can call A (2)将其与我的C ++代码(程序C)合并,以便C可以调用A

B and C are optimization algorithms, and A is a collection of benchmark functions... But before all that awesomeness can happen, I must first compile the portion of A that I need. B和C是优化算法,而A是基准函数的集合...但是,在所有令人惊奇的事情发生之前,我必须首先编译所需的A部分。 All the subroutines of A that I need are contained in one file. 我需要的所有A子例程都包含在一个文件中。 I've been getting it into shape based on information I got online (eg adding "IMPLICIT NONE" to the code and making it suitable for gfortran). 我一直在根据在线信息(例如,在代码中添加“ IMPLICIT NONE”并使其适合gfortran)来使其成形。 But I've got two stubborn bugs and a warning (I'll leave the warning for another post). 但是我有两个顽固的错误和一个警告(我将警告留在另一篇文章中)。

Here's how I am currently compiling it (via a Makefile): 这是我当前(通过Makefile)进行编译的方式:

all:
    gfortran progA.FOR
    g++ -c progC.cpp
    g++ -o Program.out progA.o progC.o
    rm *.o

But the first line fails to complete with the following errors, 但是第一行未能完成,并出现以下错误,

FIRST ERROR: 第一个错误:

SUBROUTINE TP1(MODE)
1
Error: Unclassifiable statement at (1)

RELEVANT CODE (starting from the top of the file): 相关代码(从文件顶部开始):

      IMPLICIT NONE  
      INTEGER    NMAX,MMAX,LMAX,MNNMAX,LWA,LIWA,LACTIV,N,NILI,NINL,
     /           NELI,NENL,NEX, MODE              
      PARAMETER (NMAX   = 101, 
     /           MMAX   = 50, 
     /           LMAX   = 50, 
     /           MNNMAX = NMAX + NMAX + MMAX + 2,
     /           LWA    = 2*NMAX*NMAX + 33*NMAX + 10*MMAX + 200,
     /           LIWA   = MMAX + NMAX + 150,
     /           LACTIV = 2*MMAX + 15)  
      LOGICAL    INDEX1,INDEX2

      SUBROUTINE TP1(MODE)      
      COMMON/L1/N,NILI,NINL,NELI,NENL   
      COMMON/L2/X(2)   
      COMMON/L4/GF(2)   
      COMMON/L6/FX      
      COMMON/L9/INDEX1  
      COMMON/L10/INDEX2 
      COMMON/L11/LXL    
      COMMON/L12/LXU    
      COMMON/L13/XL(2)  
      COMMON/L20/LEX,NEX,FEX,XEX(2)     
      REAL*8 X,G,GF,GG,FX,XL,XU,FEX,XEX 
      LOGICAL LXL(2),LXU(2),LEX 
      GOTO (1,2,3,4,4),MODE     
1     N=2       
      NILI=0    
      NINL=0    
      NELI=0    
      NENL=0    
      X(1)=-2.D0
      X(2)=1.D0 
      LXL(1)=.FALSE.    
      LXL(2)=.TRUE.     
      LXU(1)=.FALSE.    
      LXU(2)=.FALSE.    
      XL(2)=-1.5D0      
      LEX=.TRUE.
      NEX=1     
      XEX(1)=1.D0       
      XEX(2)=1.D0       
      FEX=0.D0  
      RETURN    
2     FX=100.D0*(X(2)-X(1)**2)**2+(1.D0-X(1))**2
      RETURN    
3     GF(2)=200.D0*(X(2)-X(1)**2)       
      GF(1)=-2.D0*(X(1)*(GF(2)-1.D0)+1.D0)      
4     RETURN    
      END       

I do not understand why this error appears since there are over 300 other subroutines declared exactly the same way (eg SUBROUTINE TP2(MODE), ..., SUBROUTINE TP300(MODE) ). 我不明白为什么会出现此错误,因为还有300多个其他子例程声明为完全相同的方式(例如SUBROUTINE TP2(MODE),...,SUBROUTINE TP300(MODE))。

SECOND ERROR: 第二次错误:

HX=TP273A(X)
1
Error: Return type mismatch of function 'tp273a' at (1) (REAL(4)/REAL(8))

RELEVANT CODE: 相关代码:

      SUBROUTINE TP273(MODE) 
      COMMON/L1/N,NILI,NIML,NELI,NENL 
      COMMON/L2/X 
      COMMON/L4/GF 
      COMMON/L6/FX 
      COMMON/L11/LXL 
      COMMON/L12/LXU 
      COMMON/L20/LEX,NEX,FEX,XEX 
      LOGICAL LEX,LXL(6),LXU(6) 
      REAL*8 X(6),FX,GF(6),FEX,XEX(6),HX,DFLOAT
      GOTO (1,2,3,4,4)MODE 
 1    N=6 
      NILI=0 
      NINL=0 
      NELI=0 
      NENL=0 
      DO 6 I=1,6 
      X(I)=0.D+0 
      XEX(I)=0.1D+1 
      LXL(I)=.FALSE. 
6     LXU(I)=.FALSE. 
      LEX=.TRUE. 
      NEX=1 
      FEX=0.D+0 
      RETURN 
 2    HX=TP273A(X) 
      FX=0.1D+2*HX*(0.1D+1+HX) 
      RETURN 
 3    HX=TP273A(X) 
      DO 7 I=1,6 
 7    GF(I)=0.2D+2*(0.16D+2-DFLOAT(I))*(X(I)-0.1D+1) 
     1       *(0.1D+1+0.2D+1*HX) 
 4    RETURN 
      END       

      REAL*8 FUNCTION TP273A (X) 
      REAL*8 X(6),DFLOAT
      TP273A=0 
      DO 10 I=1,6 
10    TP273A=TP273A+(0.16D+2-DFLOAT(I))*(X(I)-0.1D+1)**2 
      RETURN
      END

After reading Physics Forums I tried renaming the variable "TP273A" to "TP273Avar" so that it would not have the same name as the function. 在阅读了物理论坛之后,我尝试将变量“ TP273A”重命名为“ TP273Avar”,以使其与该函数的名称不同。 This did not resolve the error. 这不能解决该错误。 Also, I replaced the "1" with "F" just below "7 GF(I) = ..." and recompiled. 另外,我将“ 1”替换为“ 7 GF(I)= ...”下方的“ F”并重新编译。 Nothing changed. 没有改变。 I'm pretty sure the changes I just mentioned are necessary anyway, but there must be something else going on. 我很确定我刚才提到的更改仍然是必需的,但是还必须进行其他操作。

I have also read Data type mismatch in fortran and Function return type mismatch , so I naively tried adding "module mycode" to the top and "end module mycode" to the bottom of the file to no avail. 我也阅读了fortran中的数据类型不匹配函数返回类型不匹配 ,因此我天真地尝试将“模块mycode”添加到文件的顶部,将“结束模块mycode”添加到文件的底部无济于事。

After this is all said and done, my goal is to call these subroutines from C++ using a code similar to: 说完这些之后,我的目标是使用类似于以下的代码从C ++调用这些子例程:

#include <kitchensink>

extern"C"
{
void TP1_(int *mode);
}

int main()
{
    TP1_(2);
    return 0;
}

Once the Fortran Code compiles, I want to modify the subroutines so that C++ can pass std::vector X to TP#_(2,*X,*Y) and get back the computed value for Y. My std::vector X will replace COMMON/L2 X in each of the subroutines, and Y will be the value of FX computed in the subroutines. Fortran代码编译后,我想修改子例程,以便C ++可以将std :: vector X传递给TP #_(2,* X,* Y)并取回Y的计算值。我的std :: vector X将在每个子例程中替换COMMON / L2 X,而Y将是在子例程中计算的FX的值。 I used Mixing Fortran and C as guidance for the above C++ code. 我使用混合Fortran和C作为上述C ++代码的指南。

As for the B calls A part, I hope that it will be as simple as compiling A along with B, and adding "CALL TP1(MODE)" lines wherever I need them. 至于B调用A部分,我希望它就像将A与B一起编译,并在需要的地方添加“ CALL TP1(MODE)”行一样简单。

Any and all guidance will be greatly appreciated!!! 任何和所有指导将不胜感激!!!

You cannot have statements just in a file outside of a compilation unit. 您不能仅在编译单元外部的文件中就有语句。 These can be subroutines, functions, modules or programs. 这些可以是子例程,函数,模块或程序。 In your case you have some statements( first of them being implicit none ) and only after them there is the beginning of the subroutine TP1. 在您的情况下,您有一些语句(首先是implicit none ),只有在它们之后才有子例程TP1的开头。

Either organize the procedures in a module and leave the common part before the contains section (more work with the C++ interoperability will follow if you are a Fortran newbie) or you must include the implicit none and others in every subroutine separately. 要么将模块中的过程组织起来,然后将公共部分保留在contains部分之前(如果您是Fortran新手,则将进行C ++互操作性的更多工作),或者必须在每个子例程中分别包含implicit none和other。 Are you sure you even need this if the code worked before? 如果代码以前可以工作,您确定甚至需要此吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM