结合C ++和Fortran时未定义的引用

时间:2017-05-22 13:23:51

标签: c++ gcc fortran gfortran

我想在C ++代码中调用Fortran函数,所以我将一段C ++代码编写为fllow

#include <cstdio>

#include <math.h>

extern "C" {
  double dcadre_(double(*f)(double*), double *a, double *b, double *aerr, double *rerr, double *error, int *ier);
}

double fun(double *x) {
  return log(*x);
}

int main() {
  int ier = 500;
    double a = 0.0, b = 10.0, aerr = 0.01, rerr = 0.0001, error = 1.0;
    printf("%f\n", dcadre_(fun, &a, &b, &aerr, &rerr, &error, &ier));

  return 0;
}

这是fortran77代码:

      REAL FUNCTION DCADRE(F,A,B,AERR,RERR,ERROR,IER)
      implicit none
      EXTERNAL F
      DIMENSION T(10,10),R(10),AIT(10),DIF(10),RN(4),TS(2049)
      DIMENSION IBEGS(30),BEGIN(30),FINIS(30),EST(30)
      DIMENSION REGLSV(30)
      LOGICAL H2CONV,AITKEN,RIGHT,REGLAR,REGLSV
      REAL T,R,AIT,DIF,RN,TS,BEGIN,FINIS,EST,AITLOW
      REAL H2TOL,AITTOL,LENGTH,JUMPTL,ZERO,P1,HALF,ONE
      REAL TWO,FOUR,FOURP5,TEN,HUN,CADRE,ERROR,A,B
      REAL AERR,RERR,STEPMN,STEPNM,STAGE,CUREST,FNSIZE
      REAL PREVER,BEG,FBEG,END,FEND,STEP,ASTEP,TABS,HOVN
      REAL FN,SUM,SUMABS,ABSI,VINT,TABTLM,ERGL,ERGOAL
      REAL ERRA,ERRR,FEXTRP,ERRER,DIFF,SING,FEXTM1,ALG4O2
      REAL H2NXT,SINGNX,SLOPE,FBEG2,ALPHA
      REAL ERRET,H2TFEX,FI
      REAL RVAL,F
      integer*4 IBEGS,IER,ISTAGE,IBEG,IEND,L,N,LM1,N2,ISTEP,II,III,I,IST
     *EP2,IT,NNLEFT
      integer*4 MAXTS,MAXTBL,MXSTGE
      DATA AITLOW,H2TOL,AITTOL,JUMPTL,MAXTS,MAXTBL,MXSTGE/1.1E0,.15E0, .
     *1E0,.01E0,2049,10,30/
      DATA RN(1),RN(2),RN(3),RN(4)/.7142005E0,.3466282E0,.843751E0, .126
     *3305E0/
      DATA ZERO,P1,HALF,ONE,TWO,FOUR,FOURP5,TEN,HUN/0.0E0,0.1E0,0.5E0, 1
     *.0E0,2.0E0,4.0E0,4.5E0,10.0E0,100.0E0/
      save MAXTS,MAXTBL,MXSTGE
      ALG4O2=ALOG10(TWO)
      CADRE=ZERO
      ERROR=ZERO
      CUREST=ZERO
      VINT=ZERO
      IER=0
      LENGTH=ABS(B-A)
      IF((LENGTH.EQ.ZERO))GO TO 215
      IF((RERR.GT.P1.OR.RERR.LT.ZERO))GO TO 210
      IF((AERR.EQ.ZERO.AND.(RERR+HUN).LE.HUN))GO TO 210
      ERRR=RERR
      ERRA=ABS(AERR)
      STEPMN=(LENGTH/FLOAT(2**MXSTGE))
      STEPNM=AMAX1(LENGTH,ABS(A),ABS(B))*TEN
      STAGE=HALF
      ISTAGE=1
      FNSIZE=ZERO
      PREVER=ZERO
      REGLAR=.FALSE.
      BEG=A
      RVAL=BEG
      FBEG=F(RVAL)*HALF
      TS(1)=FBEG
      IBEG=1
      END=B
      RVAL=END
      FEND=F(RVAL)*HALF
      TS(2)=FEND
      IEND=2
5     RIGHT=.FALSE.
10    STEP=END - BEG
      ASTEP=ABS(STEP)
      IF((ASTEP.LT.STEPMN))GO TO 205
      IF((STEPNM+ASTEP.EQ.STEPNM))GO TO 205
      T(1,1)=FBEG + FEND
      TABS=ABS(FBEG) + ABS(FEND)
      L=1
      N=1
      H2CONV=.FALSE.
      AITKEN=.FALSE.
15    LM1=L
      L=L + 1
      N2=N + N
      FN=N2
      ISTEP=(IEND - IBEG)/N
      IF((ISTEP.GT.1))GO TO 25
      II=IEND
      IEND=IEND + N
      IF((IEND.GT.MAXTS))GO TO 200
      HOVN=STEP/FN
      III=IEND
      FI=ONE
      DO 10011 I=1,N2,2
        TS(III)=TS(II)
        RVAL=END-FI*HOVN
        TS(III-1)=F(RVAL)
        FI=FI+TWO
        III=III-2
        II=II-1
10011 CONTINUE
10012 CONTINUE
      ISTEP=2
25    ISTEP2=IBEG + ISTEP/2
      SUM=ZERO
      SUMABS=ZERO
      DO 10021 I=ISTEP2,IEND,ISTEP
        SUM=SUM + TS(I)
        SUMABS=SUMABS + ABS(TS(I))
10021 CONTINUE
10022 CONTINUE
      T(L,1)=T(L-1,1)*HALF+SUM/FN
      TABS=TABS*HALF+SUMABS/FN
      ABSI=ASTEP*TABS
      N=N2
      IT=1
      VINT=STEP*T(L,1)
      TABTLM=TABS*TEN
      FNSIZE=AMAX1(FNSIZE,ABS(T(L,1)))
      ERGL=ASTEP*FNSIZE*TEN
      ERGOAL=STAGE*AMAX1(ERRA,ERRR*ABS(CUREST+VINT))
      FEXTRP=ONE
      DO 10031 I=1,LM1
        FEXTRP=FEXTRP*FOUR
        T(I,L)=T(L,I) - T(L-1,I)
        T(L,I+1)=T(L,I) + T(I,L)/(FEXTRP-ONE)
10031 CONTINUE
10032 CONTINUE
      ERRER=ASTEP*ABS(T(1,L))
      IF((L.GT.2))GO TO 40
      IF((TABS+P1*ABS(T(1,2)).EQ.TABS))GO TO 135
      GO TO 15
40    DO 45 I=2,LM1
      DIFF=ZERO
      IF((TABTLM+ABS(T(I-1,L)).NE.TABTLM))DIFF=T(I-1,LM1)/T(I-1,L)
      T(I-1,LM1)=DIFF
45    CONTINUE
      IF((ABS(FOUR-T(1,LM1)).LE.H2TOL))GO TO 60
      IF((T(1,LM1).EQ.ZERO))GO TO 55
      IF((ABS(TWO-ABS(T(1,LM1))).LT.JUMPTL))GO TO 130
      IF((L.EQ.3))GO TO 15
      H2CONV=.FALSE.
      IF((ABS((T(1,LM1)-T(1,L-2))/T(1,LM1)).LE.AITTOL))GO TO 75
50    IF(REGLAR) GO TO 55
      IF((L.EQ.4))GO TO 15
55    IF(ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL) GO TO 175
      GO TO 145
60    IF(H2CONV) GO TO 65
      AITKEN=.FALSE.
      H2CONV=.TRUE.
65    FEXTRP=FOUR
70    IT=IT + 1
      VINT=STEP*T(L,IT)
      ERRER=ABS(STEP/(FEXTRP-ONE)*T(IT-1,L))
      IF((ERRER.LE.ERGOAL))GO TO 160
      IF((ERGL+ERRER.EQ.ERGL))GO TO 160
      IF((IT.EQ.LM1))GO TO 125
      IF((T(IT,LM1).EQ.ZERO))GO TO 70
      IF((T(IT,LM1).LE.FEXTRP))GO TO 125
      IF((ABS(T(IT,LM1)/FOUR-FEXTRP)/FEXTRP.LT.AITTOL))FEXTRP=FEXTRP*FOU
     *R
      GO TO 70
75    IF(T(1,LM1).LT.AITLOW) GO TO 175
      IF((AITKEN))GO TO 80
      H2CONV=.FALSE.
      AITKEN=.TRUE.
80    FEXTRP=T(L-2,LM1)
      IF((FEXTRP.GT.FOURP5))GO TO 65
      IF((FEXTRP.LT.AITLOW))GO TO 175
      IF((ABS(FEXTRP-T(L-3,LM1))/T(1,LM1).GT.H2TOL))GO TO 175
      SING=FEXTRP
      FEXTM1=ONE/(FEXTRP - ONE)
      AIT(1)=ZERO
      DO 85 I=2,L
      AIT(I)=T(I,1) + (T(I,1)-T(I-1,1))*FEXTM1
      R(I)=T(1,I-1)
      DIF(I)=AIT(I) - AIT(I-1)
85    CONTINUE
      IT=2
90    VINT=STEP*AIT(L)
      ERRER=ERRER*FEXTM1
      IF((ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL))GO TO 95
      ALPHA=ALOG10(SING)/ALG4O2 - ONE
      IER=MAX0(IER,65)
      GO TO 160
95    IT=IT + 1
      IF((IT.EQ.LM1))GO TO 125
      IF((IT.GT.3))GO TO 100
      H2NXT=FOUR
      SINGNX=SING+SING
100   IF(H2NXT.LT.SINGNX) GO TO 105
      FEXTRP=SINGNX
      SINGNX=SINGNX+SINGNX
      GO TO 110
105   FEXTRP=H2NXT
      H2NXT=FOUR*H2NXT
110   DO 115 I=IT,LM1
      R(I+1)=ZERO
      IF((TABTLM+ABS(DIF(I+1)).NE.TABTLM))R(I+1)=DIF(I)/DIF(I+1)
115   CONTINUE
      H2TFEX=-H2TOL*FEXTRP
      IF((R(L)-FEXTRP.LT.H2TFEX))GO TO 125
      IF((R(L-1)-FEXTRP.LT.H2TFEX))GO TO 125
      ERRER=ASTEP*ABS(DIF(L))
      FEXTM1=ONE/(FEXTRP - ONE)
      DO 120 I=IT,L
      AIT(I)=AIT(I) + DIF(I)*FEXTM1
      DIF(I)=AIT(I) - AIT(I-1)
120   CONTINUE
      GO TO 90
125   FEXTRP=AMAX1(PREVER/ERRER,AITLOW)
      PREVER=ERRER
      IF((L.LT.5))GO TO 15
      IF((L-IT.GT.2.AND.ISTAGE.LT.MXSTGE))GO TO 170
      ERRET=ERRER/(FEXTRP**(MAXTBL-L))
      IF((ERRET.GT.ERGOAL.AND.(ERGL+ERRET).NE.ERGL))GO TO 170
      GO TO 15
130   IF(ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL) GO TO 170
      DIFF=ABS(T(1,L))*(FN+FN)
      GO TO 160
135   SLOPE=(FEND-FBEG)*TWO
      FBEG2=FBEG+FBEG
      DO 140 I=1,4
      RVAL=BEG+RN(I)*STEP
      DIFF=ABS(F(RVAL) - FBEG2-RN(I)*SLOPE)
      IF((TABTLM+DIFF.NE.TABTLM))GO TO 155
140   CONTINUE
      GO TO 160
145   SLOPE=(FEND-FBEG)*TWO
      FBEG2=FBEG+FBEG
      I=1
150   RVAL=BEG+RN(I)*STEP
      DIFF=ABS(F(RVAL) - FBEG2-RN(I)*SLOPE)
155   ERRER=AMAX1(ERRER,ASTEP*DIFF)
      IF((ERRER.GT.ERGOAL.AND.(ERGL+ERRER).NE.ERGL))GO TO 175
      I=I+1
      IF((I.LE.4))GO TO 150
      IER=66
160   CADRE=CADRE + VINT
      ERROR=ERROR + ERRER
      IF((RIGHT))GO TO 165
      ISTAGE=ISTAGE - 1
      IF((ISTAGE.EQ.0))GO TO 220
      REGLAR=REGLSV(ISTAGE)
      BEG=BEGIN(ISTAGE)
      END=FINIS(ISTAGE)
      CUREST=CUREST - EST(ISTAGE+1) + VINT
      IEND=IBEG - 1
      FEND=TS(IEND)
      IBEG=IBEGS(ISTAGE)
      GO TO 180
165   CUREST=CUREST + VINT
      STAGE=STAGE+STAGE
      IEND=IBEG
      IBEG=IBEGS(ISTAGE)
      END=BEG
      BEG=BEGIN(ISTAGE)
      FEND=FBEG
      FBEG=TS(IBEG)
      GO TO 5
170   REGLAR=.TRUE.
175   IF(ISTAGE.EQ.MXSTGE) GO TO 205
      IF((RIGHT))GO TO 185
      REGLSV(ISTAGE+1)=REGLAR
      BEGIN(ISTAGE)=BEG
      IBEGS(ISTAGE)=IBEG
      STAGE=STAGE*HALF
180   RIGHT=.TRUE.
      BEG=(BEG+END)*HALF
      IBEG=(IBEG+IEND)/2
      TS(IBEG)=TS(IBEG)*HALF
      FBEG=TS(IBEG)
      GO TO 10
185   NNLEFT=IBEG - IBEGS(ISTAGE)
      IF((IEND+NNLEFT.GE.MAXTS))GO TO 200
      III=IBEGS(ISTAGE)
      II=IEND
      DO 190 I=III,IBEG
      II=II + 1
      TS(II)=TS(I)
190   CONTINUE
      DO 195 I=IBEG,II
      TS(III)=TS(I)
      III=III + 1
195   CONTINUE
      IEND=IEND + 1
      IBEG=IEND - NNLEFT
      FEND=FBEG
      FBEG=TS(IBEG)
      FINIS(ISTAGE)=END
      END=BEG
      BEG=BEGIN(ISTAGE)
      BEGIN(ISTAGE)=END
      REGLSV(ISTAGE)=REGLAR
      ISTAGE=ISTAGE + 1
      REGLAR=REGLSV(ISTAGE)
      EST(ISTAGE)=VINT
      CUREST=CUREST + EST(ISTAGE)
      GO TO 5
200   IER=131
      GO TO 215
205   IER=132
      GO TO 215
210   IER=133
215   CADRE=CUREST + VINT
220   DCADRE=CADRE
9000  CONTINUE
9005  RETURN
      END

然后我编译了它们:

gfortran -c DCADRE.f
g++ -c test.cc
g++ -o test test.o DCADRE.o

发生了问题:

DCADRE.o: In function `dcadre_':
DCADRE.f:(.text+0x1ac): undefined reference to `_gfortran_pow_i4_i4'
collect2: error: ld returned 1 exit status

也许我忘了链接一些Fortran库,但我不知道如何修复它。

0 个答案:

没有答案