Fortran Coder

查看: 15868|回复: 10
打印 上一主题 下一主题

[混编] 关于混合编程fortran调用C的接口问题?

[复制链接]

8

帖子

3

主题

0

精华

入门

F 币
30 元
贡献
16 点
跳转到指定楼层
楼主
发表于 2015-12-23 10:18:23 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
大神,我按照你给我的范例对程序进行了修改,以下是我改动的部分
[Fortran] 纯文本查看 复制代码
      USE ISO_C_Binding
      INCLUDE 'CHEM.TXT'
C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      TYPE, BIND(C) :: incrmnt
C       DOUBLE PRECISION(C_DOUBLE) :: y[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: ddy[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: above[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: below[lenth]
          INTEGER(C_int) :: bf,js,gross
C          Type(C_PTR), value :: incrmnt *lchild
C          Type(C_PTR), value :: incrmnt *rchild
C       Type(C_PTR), value :: incrmnt *father
      END TYPE incrmnt
C
      TYPE, BIND(C) :: strctflag
        INTEGER(C_INT) :: IFLAG,NONEAR,GSN,GSO
      END TYPE strctflag
C
      TYPE, BIND(C) :: ssflag
        INTEGER(C_INT) :: nstep,ifind,iinteg,ienlge,irecrd
      END TYPE ssflag
C
      INTERFACE
      integer(c_int) subroutine bisrch  BIND(C, Name="bisrch" )
c          import
c            integer compar(type incrmnt *,type incrmnt *);
c          TYPE(C_PTR), VALUE :: p
c          integer(c_int),value :: flag,i
      END subroutine bisrch
      END INTERFACE
      type (incrmnt) :: fst
C---------------------------------------------------------------

我把这部分加进去之后,报错为

指的是我对bisrch函数进行声明的这一段
[Fortran] 纯文本查看 复制代码
      integer(c_int) subroutine bisrch  BIND(C, Name="bisrch" )
c          import
c            integer compar(type incrmnt *,type incrmnt *);
c          TYPE(C_PTR), VALUE :: p
c          integer(c_int),value :: flag,i
      END subroutine bisrch

请问我这样声明错误在哪里?应该怎么改正?
如果我把这部分都注释,变成
[Fortran] 纯文本查看 复制代码
    INTERFACE
c     integer(c_int) subroutine bisrch  BIND(C, Name="bisrch" )
c          import
c            integer compar(type incrmnt *,type incrmnt *);
c          TYPE(C_PTR), VALUE :: p
c          integer(c_int),value :: flag,i
c      END subroutine bisrch
      END INTERFACE

那么程序会编译成功,但是没有解决问题,请问这部分应该怎么改?或者说我改动的地方是否还有其他问题?十分感谢!
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

2022

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1598 元
贡献
689 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

11#
发表于 2015-12-23 22:33:19 | 只看该作者
1. 关于 subroutine 和 function,本质上是一样的,当然写法会有一些差别。详情你可以观看本站视频教程 http://v.fcode.cn/video-subroutine_and_function.html
2.混编是需要两种语言彼此配合的,而不是随意改动其中一个。
3.你在 fortran 里面是写了参数了,可是 C 语言的代码里并没有对应的“虚参”
4.我强调了很多很多次,让你先学会单独使用 fortran 的函数和子程序。然后再学习混编。你连一点点函数调用的“概念”都没有,怎么可能学会混编呢?
5.如果你要使用 common 来共享数据,那么 fortran 也有办法实现。详情请参考《Modern Fortran Explained》第12章

8

帖子

3

主题

0

精华

入门

F 币
30 元
贡献
16 点
10#
 楼主| 发表于 2015-12-23 19:45:34 | 只看该作者
fcode 发表于 2015-12-23 18:32
1. function 和 subroutine 都可以。并没有本质区别。
2. 你必须把你所需要传递的变量都写在虚参列表里。
3 ...

群主大人,我这个程序在CVF上是链接上的,没有任何问题,出来的结果也是对的,我现在要做的工作就是把它移植到IVF上,所以我的问题是接口的问题,所有的虚参都是有定义的,在CVF上是通过COMMON /FLAG/ 和strctflag进行链接的,现在在IVF上这个链接不起作用了,所以我需要在fortran里面写一个接口让它链接上。

我这样写接口对吗:
[Fortran] 纯文本查看 复制代码
       SUBROUTINE ISAT
     1 (ELWRK, LRW, IELWRK, LIW, ANDTOL, EPSTOL, RNDTOL, STRIDE, YALL)

      USE ISO_C_Binding
      INCLUDE 'CHEM.TXT'
C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      TYPE, BIND(C) :: incrmnt
C       DOUBLE PRECISION(C_DOUBLE) :: y[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: ddy[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: above[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: below[lenth]
          INTEGER(C_int) :: bf,js,gross
C          Type(C_PTR), value :: incrmnt *lchild
C          Type(C_PTR), value :: incrmnt *rchild
C       Type(C_PTR), value :: incrmnt *father
      END TYPE incrmnt
C
      TYPE, BIND(C) :: strctflag
        INTEGER(C_INT) :: IFLAG,NONEAR,GSN,GSO
      END TYPE strctflag
C
      TYPE, BIND(C) :: ssflag
        INTEGER(C_INT) :: nstep,ifind,iinteg,ienlge,irecrd
      END TYPE ssflag
C
      INTERFACE
        subroutine bisrch()  BIND(C, Name="bisrch" )
C        function bisrch(pst)  BIND(C, Name="bisrch" )
C          import
C          Type(C_PTR)    , value :: pst
C            integer compar(type incrmnt *,type incrmnt *)
C          TYPE(C_PTR), VALUE :: p
C          integer(c_int),value :: flag,i
C        END function bisrch
        END subroutine bisrch
      END INTERFACE
C      type (incrmnt) :: fst
      type (strctflag) :: fst
C      type (ssflag) :: fst
C---------------------------------------------------------------
      EXTERNAL  BALNCE [C], INSRTD [C], ENLRGE [C], 
     &                FRMEM[C], STATIS[C], FUN, JAC
      DIMENSION YALL(KMAX), YTMP(KMAX), YQ(KMAX)
      DIMENSION ELWRK(LRW),IELWRK(LIW)

      INTEGER(4) nstep, ifind, iinteg, ienlge, irecrd
      INTEGER(4) IFLAG, NONEAR, BF, GS, JS, GSN, GSO, GROSS
      DOUBLE PRECISION ABOVE, BELOW, Y, DDY
      DIMENSION Y(KMAX),DDY(KMAX),RTOL(KMAX),ATOL(KMAX)
      DIMENSION ABOVE(KMAX+1),BELOW(KMAX+1),RPAR(KMAX),IPAR(KMAX)
c
      real*4 contm,difftm,chemtm,dintm,isatm,intgtm,srchtm,deltm,
     &       slargetm,baltm,tmchm,tmchm0
      common /stime/ difftm, contm, chemtm, dintm, isatm, intgtm,
     &               srchtm, deltm, slargetm, baltm
      common /sflag/ nstep, ifind, iinteg, ienlge, irecrd
      common /ode/ neq, mf, itol, iopt, itask, istate,rtol, atol
c
      COMMON /FIND/ Y, DDY, ABOVE, BELOW, BF, JS, GROSS
      COMMON /strctflag/ IFLAG, NONEAR, GSN, GSO

      DO I = 1, KK+1
         YTMP(I) = YALL(I)
         Y(I) = YTMP(I)
      END DO

      TMPTM0 = SECNDS(0.0)
      call bisrch
      TMPTM = SECNDS(0.0)
      SRCHTM = SRCHTM + (TMPTM - TMPTM0)

C的部分我没有改动,还跟昨天的帖子里面一样,如下:
[C] 纯文本查看 复制代码
#include "stdafx.h"

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>

#include "isatcdef.h"

struct incrmnt
{
        double y[lenth];
        double ddy[lenth];
        double above[lenth];
        double below[lenth];
        int bf;
        int js;
        int gross;
        struct incrmnt *lchild;
        struct incrmnt *rchild;
    struct incrmnt *father;
};

struct strctflag
{
        int iflag;
        int nonear;
    int gsn;
        int gso;
};
struct ssflag
{    int nstep;
     int ifind;
     int iinteg;
     int ienlge;
     int irecrd;
};

struct incrmnt FIND;
struct strctflag FLAG;
struct ssflag SFLAG;

struct incrmnt *phead=NULL,*pfind=NULL,*pfather=NULL,
*pnear=NULL,*q=NULL,*a=NULL,*f=NULL,*b=NULL,*pd=NULL;

double plus[lenth],minus[lenth];
double min=Maxmin;

void bisrch()
{
        int compar(struct incrmnt *,struct incrmnt *);

        struct incrmnt *p;
        int flag,i;
              
//        initialize pfind.

//        pfind=(struct incrmnt *)malloc(sizeof(struct incrmnt));
        pfind=new incrmnt;
        for(i=0;i<=lenth-1;i++)
                pfind->y[i]=FIND.y[i];
        pfind->lchild=NULL;
        pfind->rchild=NULL;
        pfind->father=NULL;
        pfind->bf=0;
    pfind->js=0;
    pfind->gross=0;
        
        if (phead==NULL)
        {
                phead=pfind;
                FLAG.iflag=1;
                FLAG.nonear=1;
                return;
        }
        else
/*to find the location for pfind, insert it and adjust the bitree*/  
        {
                f=NULL;a=phead;p=phead;q=NULL;
/*to find the location to insert pfind*/
                while(p!=NULL)          
                {
                        if(p->bf!=0)
                        {a=p;f=q;}         /* adjustment will start from node a,*/
                                           /*  f is the parents node of a */
                        //p->father=q;
                        q=p;
                        flag=compar(pfind,p);  /*comparing the keyword*/
                    if(flag==0)
                        {
                                for(i=0;i<=lenth-1;i++)
                                {
                                        FIND.ddy[i]=p->ddy[i];
                                }
                p->js=p->js+1;
                                FIND.js=p->js;
                                min=Maxmin;
                                pnear=NULL;
                                delete pfind;
                                FLAG.iflag=0;
                                return;
                        }
                        else
                                if(flag==1)
                                        p=p->lchild;
                                else
                                        p=p->rchild;
                }
                if (fabs(min-Maxmin)<=1.e-10)
                        FLAG.nonear=1;
                else
                {
                        FLAG.nonear=0;
                        for (i=0;i<=lenth-1;i++)
                        {
                                FIND.ddy[i]=pnear->ddy[i];
                        }
                }
                FLAG.iflag=1;
                return;
        }
}

我的接口主要就是在fortran里面添加的那一段,所以我在上个回复中只是粘贴了添加的那一部分,对不起,后来你跟我说subroutine和function在接口中的处理方式不一样,所以我又将C里面的函数bisrch()改成了上个回复中的样子,因而也没有把声明的部分写出来,实在抱歉。上面这两段在通过我写的接口编译没有问题,但是还是链接不上来,相当于没起到接口的作用,我想问一下问题出在哪里?
不好意思搞的这么麻烦你,十分感谢!

2022

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1598 元
贡献
689 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

9#
发表于 2015-12-23 18:32:32 | 只看该作者
1. function 和 subroutine 都可以。并没有本质区别。
2. 你必须把你所需要传递的变量都写在虚参列表里。
3. 所有的虚参都需要定义
4. 我建议你先学会如何单独使用 Fortran 的 function 和 subroutine,然后再学习混编。

8

帖子

3

主题

0

精华

入门

F 币
30 元
贡献
16 点
8#
 楼主| 发表于 2015-12-23 15:31:35 | 只看该作者
fcode 发表于 2015-12-23 11:10
你需要把所需的变量传递过去。把计算结果传递回来。混编并不是彻底的打通 fortran 和 c ,让他们可以自由的 ...

给你添麻烦了,十分抱歉!

8

帖子

3

主题

0

精华

入门

F 币
30 元
贡献
16 点
7#
 楼主| 发表于 2015-12-23 15:25:11 | 只看该作者
fcode 发表于 2015-12-23 11:10
你需要把所需的变量传递过去。把计算结果传递回来。混编并不是彻底的打通 fortran 和 c ,让他们可以自由的 ...

我捣鼓了一中午,实在是不知道应该怎么办,范例里面写的我感觉自己看懂了,但是到了我自己要改动的时候,又不知道看了些啥,实在是抱歉这么打扰你,我现在也只能边做边学,老板给的东西比较大而且杂,我真的没办法从头学起,如果您有空,请尽可能详细的指点一下我,十分感谢!!!

8

帖子

3

主题

0

精华

入门

F 币
30 元
贡献
16 点
6#
 楼主| 发表于 2015-12-23 15:19:41 | 只看该作者
fcode 发表于 2015-12-23 11:10
你需要把所需的变量传递过去。把计算结果传递回来。混编并不是彻底的打通 fortran 和 c ,让他们可以自由的 ...

是不是说subroutine就不行,必须要用function?可是我把他换成这种形式还是没有链接上啊?

fortran的部分:
[Fortran] 纯文本查看 复制代码
C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      TYPE, BIND(C) :: incrmnt
C       DOUBLE PRECISION(C_DOUBLE) :: y[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: ddy[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: above[lenth]
C          DOUBLE PRECISION(C_DOUBLE) :: below[lenth]
          INTEGER(C_int) :: bf,js,gross
C          Type(C_PTR), value :: incrmnt *lchild
C          Type(C_PTR), value :: incrmnt *rchild
C       Type(C_PTR), value :: incrmnt *father
      END TYPE incrmnt
C
      TYPE, BIND(C) :: strctflag
        INTEGER(C_INT) :: IFLAG,NONEAR,GSN,GSO
      END TYPE strctflag
C
      TYPE, BIND(C) :: ssflag
        INTEGER(C_INT) :: nstep,ifind,iinteg,ienlge,irecrd
      END TYPE ssflag
C
      INTERFACE
C        subroutine bisrch()  BIND(C, Name="bisrch" )
        function bisrch(iflag)  BIND(C, Name="bisrch" )
C          import
C            integer compar(type incrmnt *,type incrmnt *)
C          TYPE(C_PTR), VALUE :: p
C          integer(c_int),value :: flag,i
        END function bisrch
C        END subroutine bisrch
      END INTERFACE
      type (strctflag) :: fst
C---------------------------------------------------------------

C的部分:
[Fortran] 纯文本查看 复制代码
int bisrch(int iflag)
{
//        printf("iflag=%d\n",FLAG.iflag)
        int compar(struct incrmnt *,struct incrmnt *);

        struct incrmnt *p;
        int flag,i;
              
//        initialize pfind.

//        pfind=(struct incrmnt *)malloc(sizeof(struct incrmnt));
        pfind=new incrmnt;
        for(i=0;i<=lenth-1;i++)
                pfind->y[i]=FIND.y[i];
        pfind->lchild=NULL;
        pfind->rchild=NULL;
        pfind->father=NULL;
        pfind->bf=0;
    pfind->js=0;
    pfind->gross=0;
        
        if (phead==NULL)
        {
                phead=pfind;
                FLAG.iflag=1;
                FLAG.nonear=1;
                return FLAG.iflag;
//                return FLAG.nonear;
//                return;
        }
        else
/*to find the location for pfind, insert it and adjust the bitree*/  
        {
                f=NULL;a=phead;p=phead;q=NULL;
/*to find the location to insert pfind*/
                while(p!=NULL)          
                {
                        if(p->bf!=0)
                        {a=p;f=q;}         /* adjustment will start from node a,*/
                                           /*  f is the parents node of a */
                        //p->father=q;
                        q=p;
                        flag=compar(pfind,p);  /*comparing the keyword*/
                    if(flag==0)
                        {
                                for(i=0;i<=lenth-1;i++)
                                {
                                        FIND.ddy[i]=p->ddy[i];
                                }
                p->js=p->js+1;
                                FIND.js=p->js;
                                min=Maxmin;
                                pnear=NULL;
                                delete pfind;
                                FLAG.iflag=0;
                                return FLAG.iflag;
//                                return;
                        }
                        else
                                if(flag==1)
                                        p=p->lchild;
                                else
                                        p=p->rchild;
                }
                if (fabs(min-Maxmin)<=1.e-10)
                        FLAG.nonear=1;
                else
                {
                        FLAG.nonear=0;
                        for (i=0;i<=lenth-1;i++)
                        {
                                FIND.ddy[i]=pnear->ddy[i];
                        }
                }
                FLAG.iflag=1;
                return FLAG.iflag;
//                return;
        }
}

群主大人求帮忙!

2022

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1598 元
贡献
689 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

5#
发表于 2015-12-23 11:10:08 | 只看该作者
你需要把所需的变量传递过去。把计算结果传递回来。混编并不是彻底的打通 fortran 和 c ,让他们可以自由的访问彼此的变量。

8

帖子

3

主题

0

精华

入门

F 币
30 元
贡献
16 点
地板
 楼主| 发表于 2015-12-23 11:01:22 | 只看该作者
fcode 发表于 2015-12-23 10:35
第24行
integer(c_int) subroutine bisrch  BIND(C, Name="bisrch" )
改为

群主,改了之后现在编译通过了,但是接口还是没有接上?请问是为什么?

      TMPTM0 = SECNDS(0.0)
      call bisrch
      TMPTM = SECNDS(0.0)
      SRCHTM = SRCHTM + (TMPTM - TMPTM0)

是我这样的调用不对吗还是?

136

帖子

3

主题

0

精华

版主

F 币
1964 元
贡献
1677 点

帅哥勋章管理勋章爱心勋章新人勋章热心勋章元老勋章

板凳
发表于 2015-12-23 10:44:53 | 只看该作者
fcode 发表于 2015-12-23 10:35
第24行
integer(c_int) subroutine bisrch  BIND(C, Name="bisrch" )
改为

速度太快了,我都没来的急~
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-11-24 03:06

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表