我想知道是否有人设法以正确的方式在 Fortran 中绑定 C 结构文件。我在 gfortran 上尝试了以下操作(注意 fnum 是 gnu 扩展名)
program test_fdopen
use iso_c_binding
implicit none
type, bind(C) :: file_type
character(c_char) :: data(216) ! find compiling #include <stdio.h> int main() { printf("%d", sizeof(FILE)); }
end type
type(file_type) :: fp
integer(c_int) :: first
character(len=3) :: mode
interface
function fdopenf(num_desc, mode) bind(C,name="fdopen") result(desc)
use iso_c_binding
import :: file_type
integer(c_int) :: num_desc
character(c_char), intent(in) :: mode(*)
type(file_type) ::desc
end function
function fgetcf(desc) bind(C,name="fgetc") result(one_char)
use iso_c_binding
import :: file_type
type(file_type), intent(in) ::desc
integer(c_int) :: one_char
end function
end interface
call execute_command_line("echo coucou > haha.txt")
open(unit=22, file="haha.txt", action="read")
mode = "r" // char(0)
fp = fdopenf(fnum(22), mode)
first = fgetcf(fp)
print *, char(first), first
close(22)
end program test_fdopen
我想避免硬编码长度
216
,但遗憾的是我没有找到一个标准的方法来做到这一点
你会注意到所有使用 FILE 结构的 libc 函数都不会按值处理它,它始终是一个指针。例如。
fopen()
返回指向 FILE 结构的指针。您永远不需要取消引用该指针,然后将 FILE 结构复制到某处,您只需要跟踪指针。
因此,在您的 Fortran 代码中,正如评论中提到的,您也不需要存储 FILE 结构,只需要存储指向它的指针。因此,使用
ISO_C_BINDING
你需要的是内置的 type(C_PTR)
.
我固定版本的代码:
program test_fdopen
use iso_c_binding
implicit none
type(c_ptr) :: fp
integer(c_int) :: first
character(len=3) :: mode
interface
function fdopenf(num_desc, mode) bind(C,name="fdopen") result(desc)
use iso_c_binding
integer(c_int), value :: num_desc
character(c_char), intent(in) :: mode(*)
type(c_ptr) ::desc
end function
function fgetcf(desc) bind(C,name="fgetc") result(one_char)
use iso_c_binding
type(c_ptr), intent(in), value ::desc
integer(c_int) :: one_char
end function
end interface
call execute_command_line("echo coucou > haha.txt")
open(unit=22, file="haha.txt", action="read")
mode = "r" // char(0)
fp = fdopenf(fnum(22), mode)
first = fgetcf(fp)
print *, char(first), first
close(22)
end program test_fdopen
除了使用
type(c_ptr)
外,还必须按值将fd参数传递给fdopen
,同样将type(c_ptr)
参数传递给fgetc
。