Fortran Coder

查看: 322|回复: 7

[混编] C++与Fortran混编 type里值的传递和allocate相关的问题

[复制链接]

14

帖子

4

主题

0

精华

入门

F 币
11 元
贡献
42 点
QQ
发表于 2017-7-13 19:41:59 | 显示全部楼层 |阅读模式
20F 币
先贴代码:
[Fortran] 纯文本查看 复制代码
  module hydromodelUtil
    use iso_c_binding
    implicit none
double precision, parameter :: pi=3.141593d0

!这部分为输入值
    type ,Bind(C)::unitinfo
      integer(c_int) :: controlno
      character(c_char) :: unitname
      integer(c_int) :: unittype
      integer(c_int) :: solid
      real (c_double):: coearea
      real(c_double) ,dimension(3) :: shapepara
      integer(c_int):: pn=0
      double precision, dimension(:,:), allocatable :: plist
      real(c_double), dimension(3) :: rotationpara, tranpara
end type unitinfo

!这部分为输出值
    type ,Bind(C):: singleinfo
      integer(c_int) :: controlno 
      integer(c_int) :: unittype
      integer(c_int) :: solid
      real(c_double) :: coearea
      real(c_double):: volume
      real(c_double), dimension(3) :: center 
      integer (c_int):: pointcount, trianglecount 
      double precision, dimension(:,:), allocatable :: pointchain 
      double precision, dimension(:,:,:), allocatable :: trianglechain
    end type singleinfo
  
    contains
 subroutine cylindermeshing(r, h, cylinderinfo) Bind(C,Name="cylindermeshing")
    !DEC$ ATTRIBUTES DLLEXPORT::cylindermeshing 
    implicit none
    real(c_double) :: r, h
    type(singleinfo) :: cylinderinfo
    integer(c_int) :: polyedge=60
double precision, dimension(:,:), allocatable :: point
    real(c_double) :: dtheta
    integer(c_int) :: meshi
    
    dtheta=2*pi/real(polyedge) 

    cylinderinfo%volume=(0.5d0*polyedge*sin(dtheta)*r**2)*h
    cylinderinfo%center=(/ 0.0d0, 0.0d0, 0.5d0*h /)
    cylinderinfo%pointcount=2*polyedge
    cylinderinfo%trianglecount=4*polyedge 
    allocate(point(2,polyedge+1) )
    allocate(cylinderinfo%pointchain(3,cylinderinfo%pointcount) )
    
    do meshi=1, polyedge, 1
        point(1,meshi)=r*cos( (real(meshi)-1.0d0)*dtheta) 
        point(2,meshi)=r*sin( (real(meshi)-1.0d0)*dtheta) 
    end do
    point(:, polyedge+1)=point(:, 1) 
    
    do meshi=1, polyedge, 1
        cylinderinfo%pointchain(1:2,meshi)=point(1:2,meshi)
        cylinderinfo%pointchain(3,meshi)=0.0d0
        cylinderinfo%pointchain(1:2,polyedge+meshi)=point(1:2,meshi)
        cylinderinfo%pointchain(3,polyedge+meshi)=h
    end do
    end subroutine cylindermeshing
end module hydromodelUtil

代码太长,粘了一部分,但主题就是这些,其他大同小异。我是要在C++中以显式调用动态库的方法实现混编的,这里面有两个问题
1、type中的值不知道怎么传递,比如这行代码cylinderinfo%volume=(0.5d0*polyedge*sin(dtheta)*r**2)*h 怎么处理
2、allocate这个怎么处理   这里我有一个很笨的想法 就是给分配的数据定一个极值,就是说把大小定为常量,但是不知道后续计算时会不会产生什么不良的后果


由于Fortran和C++都是刚学不久,问的问题可能很幼稚,见笑了
导师任务时间上要的太紧,系统的学习可能来不及了,拜求大神帮帮我 ,给提供一下思路。多谢了

最佳答案

查看完整内容

在 Fortran 语言里。pointchain 大小是 1:3 * 1:cylinderinfo%pointcount 则 C 语言中正好相反,所以应该视为 0:cylinderinfo%pointcount-1 * 0:2 因此 fortran 中 pointchain(2,6) = 381 ,则 C 中应该输出 cout
回复

使用道具 举报

47

帖子

0

主题

0

精华

熟手

F 币
303 元
贡献
126 点

规矩勋章元老勋章新人勋章

QQ
发表于 2017-7-13 19:42:00 | 显示全部楼层
在 Fortran 语言里。pointchain 大小是 1:3 * 1:cylinderinfo%pointcount
则 C 语言中正好相反,所以应该视为 0:cylinderinfo%pointcount-1 * 0:2

因此 fortran 中 pointchain(2,6) = 381 ,则 C 中应该输出 cout << cylinderinfo.pointchain[ (6-1)*3+(2-1) ]
回复

使用道具 举报

47

帖子

0

主题

0

精华

熟手

F 币
303 元
贡献
126 点

规矩勋章元老勋章新人勋章

QQ
发表于 2017-7-14 08:12:15 | 显示全部楼层
本帖最后由 kyra 于 2017-7-14 08:20 编辑

问题1,无需额外处理。
问题2,不能在type里存放fortran语言的动态分配数组。否则C语言无法用标准化的手段访问。解决办法是,用 C 指针,fortran分配后把地址赋给 C 指针。具体看注释

(这方法适合于fortran的动态分配返回给 C,并不适合 C 分配的数组传递给 fortran)

[Fortran] 纯文本查看 复制代码
module hydromodelUtil
  use iso_c_binding
  implicit none
  double precision, parameter :: pi=acos(-1.d0)
  !这部分为输出值
  type ,Bind(C):: singleinfo
    integer(c_int) :: controlno
    integer(c_int) :: unittype
    integer(c_int) :: solid
    real(c_double) :: coearea
    real(c_double):: volume
    real(c_double), dimension(3) :: center
    integer (c_int):: pointcount, trianglecount
    type(C_PTR) :: pointchain , trianglechain!!!!!!!用C指针
  end type singleinfo

contains
  subroutine cylindermeshing(r, h, cylinderinfo) Bind(C,Name="cylindermeshing")
    !DEC$ ATTRIBUTES DLLEXPORT::cylindermeshing
    implicit none
    real(c_double) :: r, h
    type(singleinfo) :: cylinderinfo
    integer(c_int) :: polyedge=60
    double precision, dimension(:,:), allocatable :: point
    double precision, dimension(:,:), allocatable , target ,save :: pointchain!!!!!!!Fortran分配数组
    real(c_double) :: dtheta
    integer(c_int) :: meshi

    dtheta=2*pi/real(polyedge)

    cylinderinfo%volume=(0.5d0*polyedge*sin(dtheta)*r**2)*h
    cylinderinfo%center=(/ 0.0d0, 0.0d0, 0.5d0*h /)
    cylinderinfo%pointcount=2*polyedge
    cylinderinfo%trianglecount=4*polyedge
    allocate(point(2,polyedge+1) )
    allocate(pointchain(3,cylinderinfo%pointcount) )!!!!!!!

    do meshi=1, polyedge, 1
      point(1,meshi)=r*cos( (real(meshi)-1.0d0)*dtheta)
      point(2,meshi)=r*sin( (real(meshi)-1.0d0)*dtheta)
    end do
    point(:, polyedge+1)=point(:, 1)

    do meshi=1, polyedge, 1
      pointchain(1:2,meshi)=point(1:2,meshi)
      pointchain(3,meshi)=0.0d0
      pointchain(1:2,polyedge+meshi)=point(1:2,meshi)
      pointchain(3,polyedge+meshi)=h
    end do
    cylinderinfo%pointchain = c_loc( pointchain )!!!!!!!把地址给C指针
  end subroutine cylindermeshing
  
end module hydromodelUtil


[C++] 纯文本查看 复制代码
#include <iostream>

struct singleinfo{
  int controlno;
  int unittype;
  int solid;
  double coearea;
  double volume;
  double center[3];
  int pointcount , trianglecount;
  double *pointchain , *trianglechain;/////// C 指针
};

extern "C" {
  void cylindermeshing( double & , double & , struct singleinfo *  );
  double thirddet( double * );
}

using namespace std;

int main()
{
  struct singleinfo cylinderinfo;
  double r = 3.0;
  double h = 4.0;
  cylinderinfo.controlno  = 1;
  cylinderinfo.unittype   = 2;
  cylinderinfo.solid      = 3;
  cylinderinfo.coearea    = 4;
  cylinderinfo.volume     = 5;
  cylinderinfo.unittype   = 6;
  cylinderinfo.pointcount = 7;
  cylinderinfo.trianglecount = 8;
  cylinderinfo.center[0] = 11;
  cylinderinfo.center[1] = 11;
  cylinderinfo.center[2] = 11;
  cylindermeshing(r, h, &cylinderinfo);
  double deta[3][3];
  for (int i = 0; i < 3; i++){
    for (int j = 0; j < 3; j++){
      deta[j][i] = j*4 + i;
    }
  }
  cout << cylinderinfo.pointchain[0] << endl;
}

回复

使用道具 举报

14

帖子

4

主题

0

精华

入门

F 币
11 元
贡献
42 点
QQ
 楼主| 发表于 2017-7-14 15:37:48 | 显示全部楼层
kyra 发表于 2017-7-14 08:12
问题1,无需额外处理。
问题2,不能在type里存放fortran语言的动态分配数组。否则C语言无法用标准化的手段 ...

这里最后一行代码,假如想输出
[Fortran] 纯文本查看 复制代码
cout<<cylinderinfo.pointchain[2][6]<<endl;
传递过来的数据,该怎么处理啊  我试了一下传递过来的数据明显不对啊
回复

使用道具 举报

14

帖子

4

主题

0

精华

入门

F 币
11 元
贡献
42 点
QQ
 楼主| 发表于 2017-7-14 17:07:51 | 显示全部楼层
kyra 发表于 2017-7-14 15:54
在 Fortran 语言里。pointchain 大小是 1:3 * 1:cylinderinfo%pointcount
则 C 语言中正好相反,所以应该视 ...

真的是这样啊。。。数据都对,好厉害。

我这个程序其实是一个中间程序,是一个划分网格的程序,也就是说这里面的所有数据都需要导出来

这样看来我需要再做一个函数进行转化一下对吗

顺便问一下这个数据转换有相关的资料吗   我想学习一下
回复

使用道具 举报

47

帖子

0

主题

0

精华

熟手

F 币
303 元
贡献
126 点

规矩勋章元老勋章新人勋章

QQ
发表于 2017-7-14 18:01:23 | 显示全部楼层
不需要转换。使用的时候注意顺序即可。
回复

使用道具 举报

14

帖子

4

主题

0

精华

入门

F 币
11 元
贡献
42 点
QQ
 楼主| 发表于 2017-7-18 20:17:35 | 显示全部楼层
kyra 发表于 2017-7-13 19:42
在 Fortran 语言里。pointchain 大小是 1:3 * 1:cylinderinfo%pointcount
则 C 语言中正好相反,所以应该视 ...

重复调用这样处理的dll中的函数,发生这样的错误怎么办
allocatable array is already allocated   动态分配的数组已经被分配过了   
有没有什么办法能解决这个  ,是不是刚开始这里
[Fortran] 纯文本查看 复制代码
real(c_double),dimension(:,:),allocatable,target,save::point


少了什么参数啊?


Image 4.png
回复

使用道具 举报

485

帖子

0

主题

0

精华

宗师

F 币
1070 元
贡献
445 点

规矩勋章元老勋章新人勋章水王勋章

QQ
发表于 2017-7-19 08:11:05 | 显示全部楼层
你需要在合适的时机,释放 pointchain 数组。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

QQ|捐赠本站|Archiver|关于我们 About Us|QQ群|Fcode

GMT+8, 2017-12-18 14:55

Powered by Discuz! X3.2

© 2001-2017 Comsenz Inc.

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