[英]C to Fotran: Interoperability of a C pointer to a char array, declared in a struct
我正在创建到 C 库的 Fortran 绑定。 C 头文件定义了一个struct
,如下所示:
struct frame {
char *foo[4];
int bar;
};
(实际上,C 结构体要复杂得多,我只是将其分解为基本部分)。 现在,C 库还提供了一个为结构体赋值的函数。 出于这个问题的目的,我写了一个对这样一个函数的简化替换:
void setFrame(struct frame *fr) {
fr->bar=12;
printf("bar in C: %d\n", fr->bar);
}
(我并不真正关心foo
的值,但我确实关心bar
的值,如果foo
未正确声明,我将无法在 Fortran 端正确获取它)。 现在,这是我对上述内容的 Fortran 实现:
module binding
use iso_c_binding
implicit none
private
type, bind(c), public :: frame
integer(kind=c_int), dimension(4) :: foo
integer(kind=c_int) :: bar
end type Frame
public :: setFrame
interface
subroutine setFrame_C(fr) bind(c, name="setFrame")
import :: c_ptr
type(c_ptr), value :: fr
end subroutine setFrame_C
end interface
contains
subroutine setFrame(fr)
type(frame), intent(inout), target :: fr
call setFrame_C(c_loc(fr))
end subroutine setFrame
end module binding
这是一个测试 Fortran 程序:
program test
use binding
implicit none
type(frame) :: fr
print "(a,i0)","bar in Fortran (before calling setFrame): ",fr%bar
call setFrame(fr)
print "(a,i0)","bar in Fortran (after calling setFrame): ",fr%bar
end program test
运行上面的程序给出:
bar in Fortran (before calling setFrame): -1076110840
bar in C: 12
bar in Fortran (after calling setFrame): 12
意味着 Fortran 绑定有效。 请注意, char *foo[4]
的等价物是c_int
的整数数组。 这有点令人惊讶,因为虽然 C 整数和 C char 之间没有太大区别,但我希望 C char 是一个单字节整数。 现在,如果我以更“自然”的方式声明char *foo[4]
:
character(kind=c_char), dimension(4) :: foo
它不起作用(我没有得到fr.bar
的正确值)。 原因是,至少在 gfortran 11.2.0 中, c_int
实际上等于 4 而c_char
等于 1。甚至character(kind=c_int)
工作。 事实上, character(kind=4)
也可以工作,尽管在这种情况下编译器(正确地)发出警告。
所以我的问题是......在 Fortran 端处理char *foo[4]
真正正确的“正式”方式是什么,可移植到另一个可能以另一种方式处理 C char 的编译器?
问题是char *foo[4];
是一个由四个指向 char 的指针组成的数组,因此您在 Fortran 中的可互操作声明必须是
type, bind(c), public :: frame
type(c_ptr), dimension(4) :: foo
integer(kind=c_int) :: bar
end type Frame
您的方法只是碰巧有效,因为您可能正在 32 位平台上进行测试,其中指针与 int 具有相同的宽度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.