CとFortranは動的配列を相互に伝達する
13011 ワード
CとFortranの相互呼び出しで数値を渡す方法はいろいろありますが、F 03標準の出籠は、ISO_C_BINDINGがCとFortranの相互呼び出しを行うメリットは、より顕著です.
1、コンパイラとプラットフォームとは関係ない.
2、FortranでCのデータ型を定義することができる.
3、Interfaceインタフェースを使って声明し、はっきりしている.
ここでは主にCがFortranに動的配列を伝達する解決構想を紹介する.
Cコード:
Fortranコード:
==========================================================
2014-03-14 Cダイナミック配列をFortranに渡すコードを更新
2014-03-17 Fortranが動的配列をCに伝達するコードを補充する
1、gfortranの使用マニュアルによる:If a pointer is a dummy-argument of an interoperable procedure,it usually has to be declared using the VALUE attribute.void*matches TYPE(C_PTR)、VALUE,while TYPE(C_PTR)alone matches void**
2、増加したコードCでグローバルポインタを定義してメモリを割り当てて動的配列を開き、Fortran呼び出し、最後にCコードでメモリを解放する
3、gfortranはcとfortranファイルを直接同時にコンパイルすることができ、gccも同様にコンパイルパラメータを追加する必要がある
まとめ:subroutine定義CのinterfaceではなくFunctionを使用することをお勧めします.動的配列に割り当てられたメモリは空にし、メモリの漏洩を避け、ポインタを使用すると空のポインタを指すことを忘れないでください.
************************************
C動的配列をFortranに渡す
C pass dynamic array to Fortran
************************************
Cコード:
#include #include//define a struct - struct conn{ int ind; float *list; int length;};//define a pointer structstruct conn *abc=NULL;//length of dynamic arrayint array_len=0,struct_len=0;//define a pointer to pointerfloat *vector2=NULL;/* float array printing function */void print_float_array(float *array, int len) - { int i; for(i=0; iFortranコード:
- module dynamicuse,intrinsic::iso_c_bindingimplicit none! Define struct - type,bind(c)::connect integer(c_int)::ind type(c_ptr)::list integer(c_int)::lengthend type- interface ! Method 1 via subroutine- subroutine dynamic_array(length,a,n)bind(c,name='dynamic_array') import implicit none integer(c_int),intent(in),value::length integer(c_int),intent(out)::n type(c_ptr),intent(out)::a end subroutine ! Mehtod 2 via function- type(c_ptr) function dynamic_array2(length,n)bind(c,name='d_array') import implicit none integer(c_int),intent(in),value::length integer(c_int),intent(out)::n end function ! Pass dynamic struct array via function- type(c_ptr) function dynamic_struct(length,n)bind(c,name='d_struct') import implicit none integer(c_int),intent(in),value::length integer(c_int),intent(out)::n end function ! Clear struct array- subroutine clear_struct()bind(c,name='clear_struct') import implicit none end subroutine ! Clear array- subroutine clear_array()bind(c,name='clear_array') import implicit none end subroutineend interfaceend module- program testuse dynamicimplicit nonereal,pointer::array(:)integer,pointer::nntype(c_ptr)::c_array,c_structtype(connect),pointer::conn(:)integer::i,j,knullify(array)nn=>NULL()c_array=c_null_ptri = 10j = 0call dynamic_array(i,c_array,j)!c_array = dynamic_array2(i,j)write(*,*)i,jcall c_f_pointer(c_array,array,[j])write(*,*)write(*,*)arrayc_array=c_null_ptrc_struct = c_null_ptrarray=>null()i = 2*2j = 0c_struct = dynamic_struct(i,j)write(*,*)i,jcall c_f_pointer(c_struct,conn,[j])- do i=1,j array=>null() call c_f_pointer(conn(i)%list,array,[conn(i)%length]) write(*,*)"Index:",i write(*,*)"List:",(array(k),k=1,size(array))enddocall clear_struct()call clear_array()end program
************************************
Fortran動的配列をCに渡す
Fortran pass dynamic array to C
***********************************
Fortranコード:
- module f2c_dynamicuse,intrinsic::iso_c_bindingimplicit noneinteger(c_int),allocatable,target::ind(:)contains- type(c_ptr) function init_array(n1,n2)bind(c,name="allocArray") implicit none integer(c_int),intent(in),value::n1 integer(c_int),intent(out)::n2 integer::i write(*,*)"************************" write(*,*)"Fortran" write(*,*)"************************" write(*,*)"input:",n1,n2 call clear_array() init_array = c_null_ptr allocate(ind(n1+6))- do i=1,n1+6 ind(i) = i**2+2 write(*,*)"index:",i,"value:",ind(i) enddo n2 = n1 + 6 write(*,*)"array size:",n2 init_array = c_loc(ind(1)) write(*,*)"Return pointer" return end function - subroutine init_array2(n1,n2,a)bind(c,name="allocArray2") implicit none integer(c_int),intent(in),value::n1 integer(c_int),intent(out)::n2 type(c_ptr),intent(out)::a integer::i write(*,*)"************************" write(*,*)"Fortran" write(*,*)"************************" write(*,*)"input:",n1,n2 call clear_array() a = c_null_ptr allocate(ind(n1+2))- do i=1,n1+2 ind(i) = i**3-1 write(*,*)"index:",i,"value:",ind(i) enddo n2 = n1 + 2 write(*,*)"array size:",n2 a = c_loc(ind(1)) write(*,*)"Return pointer" return end subroutine- subroutine clear_array()bind(c,name="clearArray") implicit none if(allocated(ind))then deallocate(ind) write(*,*)"Clear successfully" endif end subroutineend module f2c_dynamic
Cコード:
#include /* malloc */ #include /* printf */ int *allocArray(int ,int *);//via fortran function void allocArray2(int,int *,int **);//via fortran subroutine void clearArray(); /* float array printing function */ void print_int_array(int *array, int len) - { int i; for(i=0; i転載先:https://www.cnblogs.com/pasuka/p/3360928.html
1、コンパイラとプラットフォームとは関係ない.
2、FortranでCのデータ型を定義することができる.
3、Interfaceインタフェースを使って声明し、はっきりしている.
ここでは主にCがFortranに動的配列を伝達する解決構想を紹介する.
Cコード:
1 #include /* malloc */
2 #include /* printf */
3 struct my_struct{
4 int num; /* length of array*/
5 int *array; /* dynamic array*/
6 }my_struct;
7 int j=12;
8 struct my_struct make_array(){
9 struct my_struct tmp;
10 int i;
11 tmp.num = j;
12 /* initialize array */
13 tmp.array = (int*)malloc(tmp.num*sizeof(int));
14 for(i=0;i1)*(i+1);
15 j+=3;
16 return tmp;
17 }
Fortranコード:
program f_call_c
use,intrinsic::iso_c_binding
implicit none
! define same struct in C
type,bind(c)::my_struct
integer(c_int)::nn
type(c_ptr)::array
end type
interface
type(my_struct) function make_array() bind(c,name='make_array')
import !! Make iso_c_binding and my_struct visible here
end function
endinterface
integer(C_INT), pointer :: array(:) => NULL()
type(my_struct)::xyz
integer::j
do j=1,3
xyz = make_array()
call c_f_pointer(xyz%array,array,[xyz%nn])
write(*,*)xyz%nn
write(*,*)array
enddo
end program
==========================================================
2014-03-14 Cダイナミック配列をFortranに渡すコードを更新
2014-03-17 Fortranが動的配列をCに伝達するコードを補充する
1、gfortranの使用マニュアルによる:If a pointer is a dummy-argument of an interoperable procedure,it usually has to be declared using the VALUE attribute.void*matches TYPE(C_PTR)、VALUE,while TYPE(C_PTR)alone matches void**
2、増加したコードCでグローバルポインタを定義してメモリを割り当てて動的配列を開き、Fortran呼び出し、最後にCコードでメモリを解放する
3、gfortranはcとfortranファイルを直接同時にコンパイルすることができ、gccも同様にコンパイルパラメータを追加する必要がある
まとめ:subroutine定義CのinterfaceではなくFunctionを使用することをお勧めします.動的配列に割り当てられたメモリは空にし、メモリの漏洩を避け、ポインタを使用すると空のポインタを指すことを忘れないでください.
************************************
C動的配列をFortranに渡す
C pass dynamic array to Fortran
************************************
Cコード:
#include #include//define a struct - struct conn{ int ind; float *list; int length;};//define a pointer structstruct conn *abc=NULL;//length of dynamic arrayint array_len=0,struct_len=0;//define a pointer to pointerfloat *vector2=NULL;/* float array printing function */void print_float_array(float *array, int len) - { int i; for(i=0; i
- module dynamicuse,intrinsic::iso_c_bindingimplicit none! Define struct - type,bind(c)::connect integer(c_int)::ind type(c_ptr)::list integer(c_int)::lengthend type- interface ! Method 1 via subroutine- subroutine dynamic_array(length,a,n)bind(c,name='dynamic_array') import implicit none integer(c_int),intent(in),value::length integer(c_int),intent(out)::n type(c_ptr),intent(out)::a end subroutine ! Mehtod 2 via function- type(c_ptr) function dynamic_array2(length,n)bind(c,name='d_array') import implicit none integer(c_int),intent(in),value::length integer(c_int),intent(out)::n end function ! Pass dynamic struct array via function- type(c_ptr) function dynamic_struct(length,n)bind(c,name='d_struct') import implicit none integer(c_int),intent(in),value::length integer(c_int),intent(out)::n end function ! Clear struct array- subroutine clear_struct()bind(c,name='clear_struct') import implicit none end subroutine ! Clear array- subroutine clear_array()bind(c,name='clear_array') import implicit none end subroutineend interfaceend module- program testuse dynamicimplicit nonereal,pointer::array(:)integer,pointer::nntype(c_ptr)::c_array,c_structtype(connect),pointer::conn(:)integer::i,j,knullify(array)nn=>NULL()c_array=c_null_ptri = 10j = 0call dynamic_array(i,c_array,j)!c_array = dynamic_array2(i,j)write(*,*)i,jcall c_f_pointer(c_array,array,[j])write(*,*)write(*,*)arrayc_array=c_null_ptrc_struct = c_null_ptrarray=>null()i = 2*2j = 0c_struct = dynamic_struct(i,j)write(*,*)i,jcall c_f_pointer(c_struct,conn,[j])- do i=1,j array=>null() call c_f_pointer(conn(i)%list,array,[conn(i)%length]) write(*,*)"Index:",i write(*,*)"List:",(array(k),k=1,size(array))enddocall clear_struct()call clear_array()end program
************************************
Fortran動的配列をCに渡す
Fortran pass dynamic array to C
***********************************
Fortranコード:
- module f2c_dynamicuse,intrinsic::iso_c_bindingimplicit noneinteger(c_int),allocatable,target::ind(:)contains- type(c_ptr) function init_array(n1,n2)bind(c,name="allocArray") implicit none integer(c_int),intent(in),value::n1 integer(c_int),intent(out)::n2 integer::i write(*,*)"************************" write(*,*)"Fortran" write(*,*)"************************" write(*,*)"input:",n1,n2 call clear_array() init_array = c_null_ptr allocate(ind(n1+6))- do i=1,n1+6 ind(i) = i**2+2 write(*,*)"index:",i,"value:",ind(i) enddo n2 = n1 + 6 write(*,*)"array size:",n2 init_array = c_loc(ind(1)) write(*,*)"Return pointer" return end function - subroutine init_array2(n1,n2,a)bind(c,name="allocArray2") implicit none integer(c_int),intent(in),value::n1 integer(c_int),intent(out)::n2 type(c_ptr),intent(out)::a integer::i write(*,*)"************************" write(*,*)"Fortran" write(*,*)"************************" write(*,*)"input:",n1,n2 call clear_array() a = c_null_ptr allocate(ind(n1+2))- do i=1,n1+2 ind(i) = i**3-1 write(*,*)"index:",i,"value:",ind(i) enddo n2 = n1 + 2 write(*,*)"array size:",n2 a = c_loc(ind(1)) write(*,*)"Return pointer" return end subroutine- subroutine clear_array()bind(c,name="clearArray") implicit none if(allocated(ind))then deallocate(ind) write(*,*)"Clear successfully" endif end subroutineend module f2c_dynamic
Cコード:
#include /* malloc */ #include /* printf */ int *allocArray(int ,int *);//via fortran function void allocArray2(int,int *,int **);//via fortran subroutine void clearArray(); /* float array printing function */ void print_int_array(int *array, int len) - { int i; for(i=0; i