[英]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.