【问题标题】:Access 2d arrays passed from C as pointers in Fortran访问从 C 传递的二维数组作为 Fortran 中的指针
【发布时间】:2016-09-30 20:25:10
【问题描述】:

如何在 Fortran 中访问作为 C 函数指针传递的二维数组。下面是我的代码

    program linkFwithC
    use iso_c_binding
    implicit none
    interface
      subroutine my_routine(p,r) bind(c,name='print2')
        import :: c_ptr
        import :: c_int
        type(c_ptr), value :: p
        integer(c_int), value :: r
      end subroutine
    end interface
    REAL, POINTER :: PTR2
    integer i,j
    integer,parameter ::n=3
    real (c_double), allocatable, target :: xyz(:,:)
    real (c_double), target :: abc(3,3)
    type(c_ptr) :: cptr
    allocate(xyz(n,n))
    cptr = c_loc(xyz(1,1))

    !Inputing array valyes

    xyz(1,1)= 1
    xyz(1,2)= 2
    xyz(1,3)= 3
    xyz(2,1)= 4
    xyz(2,2)= 5
    xyz(2,3)= 6
    xyz(3,1)= 7
    xyz(3,2)= 8
    xyz(3,3)= 9


    call my_routine(cptr,n)

    do j=1,n
    do i=1,n

    print*,"xyz(i,j)",i,j,xyz(j,i)

    enddo
    enddo
    deallocate(xyz)
 ! pause
  end program linkFwithC

下面是我的 C 代码

  #include <stdio.h>
  void print2(double *p, int n)
  {
   printf("Array from C is \n");
   double *dptr;
   int i,j;
   dptr = (double *)p;
   for ( i = 0; i < n; i++)
   {
     for ( j = 0; j<n; j++)
      {
       printf("%.6g \t",dptr[i*n+j]);

      *(p+i*n+j)=1;
      printf("\n");
     }
  }
 }

下面是输出

Array from C is
1       4       7
1       5       8
1       6       9
 xyz(i,j)           1           1   1.00000000000000
 xyz(i,j)           2           1   1.00000000000000
 xyz(i,j)           3           1   1.00000000000000
 xyz(i,j)           1           2   4.00000000000000
 xyz(i,j)           2           2   5.00000000000000
 xyz(i,j)           3           2   6.00000000000000
 xyz(i,j)           1           3   7.00000000000000
 xyz(i,j)           2           3   8.00000000000000
 xyz(i,j)           3           3   9.00000000000000
*** glibc detected *** ./main.exe: free(): invalid next size (normal): 0x000000000093c290 ***
======= Backtrace: =========
/lib64/libc.so.6[0x320ea75f4e]
/lib64/libc.so.6[0x320ea78cf0]
./main.exe[0x408786]
./main.exe[0x4240bc]
./main.exe[0x429f54]
./main.exe[0x402e63]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x320ea1ed5d]
./main.exe[0x402d69]
======= Memory map: ========

我无法在 Fortran 中打印修改后的值。任何人都可以提出工资输出的可能原因吗?

【问题讨论】:

  • 您确定 fortran 中的二维可分配数组具有像静态二维数组一样的连续内存吗?因为结果似乎证明了相反。并且不要忘记 C 和 FORTRAN 在涉及多维数组时是转置的。
  • @Jean-FrançoisFabre 是的,他们有,事实上他们总是连续的记忆。您可以在 Google 上搜索一个将指针从 c 传递到 lapack fortran 的示例程序。
  • @iharob 我问是因为看起来他们不是你不同意吗?我根本不是 FORTRAN 专家。只是为辩论加油:)
  • 你能不能edit你的C代码并用*(p+i*n+j)=i*n+j;替换*(p+i*n+j)=1;(当然还有相关的输出)。

标签: c multidimensional-array fortran fortran-iso-c-binding


【解决方案1】:

首先,你的代码不是FORTRAN,而是Fortran; C 语言互操作性的设施要晚得多。二、如下代码

#include <stdio.h>
void print2(double *p, int n)
{  
  double *dptr;
  int i,j;

  /* Why are you making a copy here? 
   * Did you intent to pass by value or reference?
   */
  dptr = p;
  printf("Array from C is \n");
  for(i = 0; i < n; i++){
    for(j = 0; j < n; j++){
      printf("%.6g \t", dptr[i*n+j]);
      *(p+i*n+j)=1;
      printf("\n");
    }
  }
}

module mymod

  use ISO_C_binding, only: &
       c_ptr, &
       c_int

  ! Explicit typing only
  implicit none

  interface
     subroutine my_routine(p, r) bind(c, name='print2')
       import :: c_ptr, c_int
       type(c_ptr), value    :: p
       integer(c_int), value :: r
     end subroutine my_routine
  end interface

end module mymod

program main

    use ISO_Fortran_env, only: &
    compiler_version, &
    compiler_options

    use ISO_C_binding, only: &
     c_double, &
     c_ptr, &
     c_loc

    use mymod, only: &
     my_routine

    ! Explicit typing only
    implicit none

    integer i, j
    integer, parameter :: N = 3
    real(c_double), allocatable, target :: xyz(:,:)
    type(c_ptr) :: cptr

    ! Allocate memory
    allocate(xyz(N, N))

    ! Get C-language address
    cptr = c_loc(xyz(1,1))

    ! Inputting array values
    xyz(1,1)= 1
    xyz(1,2)= 2
    xyz(1,3)= 3
    xyz(2,1)= 4
    xyz(2,2)= 5
    xyz(2,3)= 6
    xyz(3,1)= 7
    xyz(3,2)= 8
    xyz(3,3)= 9

    call my_routine(cptr, N)

    do j=1, N
       do i=1, N
      print *, "xyz(i,j)", i, j, xyz(j, i)
       end do   
    end do

    ! Release memory
    deallocate(xyz)

    print '(/4a/)', &
    ' This file was compiled using ', compiler_version(), &
    ' using the options ', compiler_options()

end program main

产量

gfortran -Wall -o main.exe  print2.c mymod.f90 main.f90
./main.exe

Array from C is 
1   
4   
7   
2   
5   
8   
3   
6   
9   
 xyz(i,j)           1           1   1.0000000000000000     
 xyz(i,j)           2           1   1.0000000000000000     
 xyz(i,j)           3           1   1.0000000000000000     
 xyz(i,j)           1           2   1.0000000000000000     
 xyz(i,j)           2           2   1.0000000000000000     
 xyz(i,j)           3           2   1.0000000000000000     
 xyz(i,j)           1           3   1.0000000000000000     
 xyz(i,j)           2           3   1.0000000000000000     
 xyz(i,j)           3           3   1.0000000000000000     

 This file was compiled using GCC version 6.1.1 20160802 using the options -mtune=generic -march=x86-64 -Wall

【讨论】:

  • 你能解释一下你修复了什么吗?
  • 看不到任何变化
  • 是的,c 代码有一点变化:使用 void* 并且它起作用了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 2013-02-13
相关资源
最近更新 更多