我正在学习 Fortran 2003。作为一项培训任务,我正在尝试从 Fortran 2003 调用使用不透明指针的 C 库:
struct foobar_s;
typedef struct foobar_s *foobar;
foobar foo_create(enum foo, unsigned int);
void foo_destroy(foobar);
我在互联网上找到的大多数建议都告诉我将foobar
类型描述为type(c_ptr)
,所以以下应该可以工作:
!foobar foo_create(enum foo, unsigned int);
function foo_create(mode,n) bind(c) ret(foo)
type(c_ptr) :: foo
integer(kind(ENUM_FOO_CONSTANT)), value :: mode
integer(kind=c_int), value :: n
end function
这声明foo_create
为返回 avoid*
而不是foobar
= struct foobar_s *
,但无论如何它都适用于现代架构。
我一直在尝试创建一个独特的 Fortran 类型,更接近不透明 C 指针的意图。唯一对我有用的是:
type, bind(c) :: foobar
private
type(c_ptr) :: ptr
end type
对应于:
typedef struct {
void * ptr;
} foobar;
在 C 侧。现在,C 标准的 §6.7.2.1 保证 a 开头的struct
地址是第一个元素的地址(对吗?)但它的末尾可能有一些填充(但在我使用的架构上没有,因为指针是自对齐的),所以这整个装置在我的机器上工作:
!foobar foo_create(enum foo, unsigned int);
function foo_create(mode,n) bind(c) ret(foo)
type(foobar) :: foo
integer(kind(ENUM_FOO_CONSTANT)), value :: mode
integer(kind=c_int), value :: n
end function
!void foo_destroy(foobar);
sobroutine foo_destroy(foo) bind(c)
type(foobar), value :: foo
end subroutine
我已经验证 Valgrind 对于调用 C 函数的程序foo_create()
和foo_destroy()
使用这种类型定义的 Fortran 程序没有显示错误。尽管如此,它仍然不能作为一个确定的证据。
struct { void * ptr }
具有相同大小和位模式的假设是否struct foobar_s *
会中断?这是在 Fortran 2003 中包装不透明 C 指针(并创建不同类型)的最佳方法吗?