Fortran iso_c_绑定c_ptrs:如何从C指针(Fortran数组)元素设置C双指针数组元素

jv2fixgn  于 2022-12-22  发布在  其他
关注(0)|答案(1)|浏览(111)

我正在修改一些预先存在的代码以使用Fortran iso_c_binding标准。在Fortran端我定义了一个整数,这个整数通过C malloc为数组存储空间,我有一个类似的变量(但是一个实数)在Fortran端被设置为许多值。实数被用来设置值,在C中曾经是整数。我如何修改下面的程序以使用iso_c_binding实现这一点?Fortran和/或C代码必须更改吗?
文件main.f90:

program main
       use the_interface
       use iso_c_binding, only : c_int,c_ptr,c_loc

       implicit none
       type(myint), pointer :: intvar
   
       type(c_ptr), pointer :: value_ptr

       type(real), allocatable, target :: value(:)
       type(c_ptr) :: myint_ptr 

       integer ans,i

       allocate(value(10),value_ptr)

       value_ptr = c_loc(value)

       do i = 1,10
         value(i) = real((i-1) * 3 + (i-1),4)
       end do

       ans = get_storage(myint_ptr)
       ans = set_source(myint_ptr,value_ptr)

       ans = print_source(myint_ptr)
       end program main

文件测试c:

#include <stdio.h>
#include <stdlib.h>

typedef int int_type;

struct myint {
   int value;
};

#define NUM 10

int get_storage_ (int_type **dest)  
{
  *dest = (int_type *)malloc(NUM * sizeof(int_type));

  if (!*dest) {
      return -1;
  }

  return 0;
}

int set_source_ (struct myint **dest, struct myint *source)
{
  int i;
  int counter = 0;

  for (i = 0;i < NUM;i++)
  {
    /* (*dest + i)->value = i * 3 + i; */
     (*dest + i)->value = (source + i)->value;

    if (!(++counter % 5))
    {
      printf ("\n");
      counter = 0;
    }
  }

  return 0;
}

int print_source_ (struct myint **dest)
{
  int i;
  int counter = 0;
  int errors = 0;

  for (i = 0;i < NUM;i++)
  {
    if (((*dest + i)->value) != (i * 3 + i))
    {
      printf ("Error at %d %d != %d ",i, ((*dest + i)->value),(i * 3 + i));
      errors ++;
    }
    else
    {
      printf ("Value at %d = %d ",i,(*dest + i)->value);
    }

    counter++;

    if (!(counter % 5))
    {
      printf ("\n");
      counter = 0;
    }
  }

  printf ("\n%d values weren't set correctly!\n",errors);
  printf ("%d values were set correctly!\n\n",NUM - errors);

  return 0;
}

将_接口. f90归档:

module the_interface
       use iso_c_binding, only: c_int,c_ptr,c_float

       type, bind(c) :: myint
         integer(c_int) :: int_tmp
       end type

       type, bind(c) :: myfloat
         real(c_float) :: float_tmp
       end type

         function get_storage(address)bind(c,name="get_storage_")
             import :: c_int, c_ptr, myint
             implicit none
             type(c_ptr), intent(inout) :: address
             integer(c_int) :: get_storage
         end function

         function set_source(address, value)bind(c,name="set_source_")
             import :: c_int, c_ptr, myint
             implicit none
             type(c_ptr), intent(inout) :: address
             type(c_ptr), intent(inout) :: value
             integer(c_int) :: set_source
         end function

         function print_source(address)bind(c,name="print_source_")
             import :: c_int, c_ptr, myint
             implicit none
             type(c_ptr), intent(inout) :: address
             integer(c_int) :: print_source
         end function
       end interface

       end module the_interface

编译和运行:

gcc      -g -c test.c     -o test.o 
  gfortran -g -c the_interface.f90 -o the_interface.o
  gfortran -g -c main.f90     -o main.o
  gfortran -g main.o test.o -o main.exe -lgfortran
  ./main.exe

输出:
0 38195424处出错!= 0 1 38195424处出错!= 4 2 38195424处出错!= 8 3 38195424处出错!= 12 4 38195424处出错!= 16 5 38195424处出错!= 20 6 38195424处出错!= 24错误位置7 38195424!= 28错误位置8 38195424!= 32错误位置9 38195424!= 36
10个值设置不正确! 0个值设置正确!
(1)我尝试修改test. c文件中set_source_routine的以下行:

(*dest + i)->value = (source + i)->value;

我希望输出为:
0 = 0处的值1 = 4处的值2 = 8处的值3 = 12处的值4 = 16处的值5 = 20处的值6 = 24处的值7 = 28处的值8 = 32处的值9 = 36处的值
0个值设置不正确! 10个值设置正确!
(2)我试着从set_source_function的"struct myint * source"形参定义中删除"struct",但无法编译。
(3)在set_source_中使用"source [i]. value"而不是"(source + i)-〉value"也没有达到我想要的效果,它给出了同样错误的输出。
(4a)如果我把set_source_function形参的定义改为"struct myint**source"而不是"struct myint * source",我仍然会得到9个错误的值,第一个值是0。(4b)如果在 * error * printf中我也把第二个printf格式说明符从" % d"改为" % f",那么数组元素打印出来时都是0。

xqk2d5yq

xqk2d5yq1#

这里有一个解决方案,您可以改进iso_c_binding接口代码吗?

int set_source_ (struct myint **dest, float **source)
{
  int i;
  int counter = 0;

  for (i = 0;i < NUM;i++)
  {
    /* (*dest + i)->value = i * 3 + i; */
     (*dest + i)->value = (*source)[i];

    if (!(++counter % 5))
    {
      printf ("\n");
      counter = 0;
    }
  }

  return 0;
}

相关问题