C和Fortran的相互调用传递数值的方法有很多,但是F03标准的出笼,使用ISO_C_BINDING进行C和Fortran的互相调用有着更显著的优势:
1、与编译器和平台无关;
2、Fortran中可以定义C的数据类型;
3、使用Interface接口声明,清晰明了;
这里主要介绍C传递动态数组给Fortran的一种解决思路。
C代码:
1 #include <stdlib.h> /* malloc */ 2 #include <stdio.h> /* 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;i<tmp.num;i++)tmp.array[i]=(i+1)*(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同样亦可不过需要添加编译参数
小结:推荐使用Function而不是subroutine定义C的interface,分配给动态数组的内存要清空,避免内存泄漏,使用指针的话用完后记得指向空指针。
************************************
C传递动态数组到Fortran
C pass dynamic array to Fortran
************************************
C代码:
#include <stdlib.h>
#include <stdio.h>
// define a struct
- struct conn{
int ind;
float *list;
int length;
};
// define a pointer struct
struct conn *abc=NULL;
// length of dynamic array
int array_len=0,struct_len=0;
// define a pointer to pointer
float *vector2=NULL;
/* float array printing function */
void print_float_array(float *array, int len)
- {
int i;
for(i=0; i<len; i++)
printf("%f | ", array[i]);
putchar('\n');
}
void clear_array(void)
- {
- if(vector2!=NULL){
free(vector2);
vector2=NULL;
printf("Clear pointer successfully\n");
}
- else{
printf("Already NULL!\n");
}
}
// Method 1
void dynamic_array(int n1,float **a,int *n2)
- {
int i;
if(vector2!=NULL)clear_array();
// Allocate array
vector2 = (float*)malloc(n1*2*sizeof(float));
// Set values
for(i=0;i<n1*2;i++){
vector2[i] = (float)i*i+1.0;}
// display array
print_float_array(vector2,n1*2);
//
*a = vector2;
*n2 = 2*n1;
// Set length of array
array_len =