gpt4 book ai didi

arrays - 将 Fortran 派生类型数组作为结构传递给 C 函数

转载 作者:行者123 更新时间:2023-12-05 04:28:37 26 4
gpt4 key购买 nike

我有一个具有匹配 C 结构的 Fortran 派生类型。我正在创建派生类型的数组,我想将此数组传递给 C 函数。这是我的 Fortran 代码

module tmod

use iso_c_binding

integer, parameter :: nstring = 22
integer, parameter :: ntype = 3
!! Type with a bind(c)
type, bind(c) :: mystruct
character (c_char) :: hello (nstring)
character (c_char) :: world (nstring)
integer (c_int) :: ii
end type mystruct

interface !! Function on the C side
integer (c_int) function testfunc (t, asize) bind(C, name="testfunc")
use iso_c_binding
import mystruct
type (mystruct) :: t (:) !< array of struct/derived type
integer (c_int), value :: asize !< Size of the array
end function testfunc
end interface

end module tmod


program testprog

use tmod
use iso_c_binding

type(mystruct), target :: t (0:ntype-1) !< Array of derived type set up with C-like indicies
integer (c_int) :: i
!! Initialize the struct array
do j = 0,ntype-1
t(j)%hello = "HelLo"//c_null_char
t(j)%world = "World"//c_null_char
t(j)%ii = j-3
enddo
!! Call C function
i = testfunc(t, ntype)
end program testprog

我的 C 代码循环遍历结构并打印整数

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

int const nstring = 22; /* matches string size from fortran */
struct mystruct{
char hello[22];
char world[22];
int ii ;
}mystruct;

int testfunc (struct mystruct * t[], int asize ) {
/* Loop through array and print index then ii value */
for (int j = 0; j < asize ; j++) {
printf ("%d \n", j);
printf ("%d \n", t[j]->ii);
}
return 0;
}

这些使用 icc 版本 2021.5.0 和 ifort 版本 2021.5.0 或 gcc 版本 11.2.0 编译(这会删除关于在此处为 mystruct t[] 声明的注释)。它打印出第一个循环的结果。它在第二次通过循环时给我一个段错误。我不能按值传递数组,因为它是一个数组,这显然是不允许的。
如果我在没有指针的情况下定义我的 C 函数

int testfunc (struct mystruct t[], int asize ) 

程序运行到最后,但没有打印出正确的信息。如何将这个 Fortran 数组传递给 C 函数?

最佳答案

您的 Fortran 接口(interface)有一个假定形状的伪参数 t。具有此假定形状数组的 testfunc 的接口(interface)不能与 C 函数的形式参数 struct mystruct * t[] 互操作。可互操作的 C 函数必须具有与 a pointer to CFI_cdesc_t object 关联的参数。

也就是说,在您显示的代码中几乎没有理由要使用假设形状的虚拟参数,因为您还传递了数组的大小。而是使用显式形状参数:

interface !! Function on the C side
integer (c_int) function testfunc (t, asize) bind(C, name="testfunc")
use iso_c_binding
import mystruct
integer (c_int), value :: asize !< Size of the array
type (mystruct) :: t (asize) !< array of struct/derived type
end function testfunc
end interface

这将导致下一个问题:您不需要struct mystruct * t[],而是struct mystruct *:

int testfunc (struct mystruct *t, int asize ) {
/* Loop through array and print index then ii value */
for (int j = 0; j < asize ; j++) {
printf ("%d \n", j);
printf ("%d \n", t[j].ii);
}
return 0;
}

或者,如果出于某种原因您确实需要 assumed-shape 参数:

interface !! Function on the C side
integer (c_int) function testfunc (t) bind(C, name="testfunc")
use iso_c_binding
import mystruct
type (mystruct) :: t (:) !< array of struct/derived type
end function testfunc
end interface

你可以让它与

互操作
int testfunc (CFI_cdesc_t* t) {
/* Loop through array and print index then ii value */
struct mystruct *address;
CFI_index_t subscript[1];
for (int j = 0; j < t->dim[0].extent ; j++) {
subscript[0] = j;
printf ("%d \n", j);
address = (struct mystruct *) CFI_address(t, subscript);
printf ("%d \n", address->ii);
}
return 0;
}

无论哪种方式,您都可能希望像这样处理作业

  t(j)%hello = "HelLo"//c_null_char

将数组 t(j)%hello 设置为 "H" 的 22 个元素。你会希望右侧本身是一个包含 22 个元素的数组,比如:

  t(j)%hello = [character(c_char) :: "H", "e", "l", "L", "o", c_null_char, [(" ", i=1,16)]]

并且不要忘记自由地使用implicit none 来减少惊喜的可能性。

关于arrays - 将 Fortran 派生类型数组作为结构传递给 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72549960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com