C和Fortran互相传递动态数组
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 = n1*2;
}
// Method 2
float* d_array(int n1,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;}
print_float_array(vector2,n1*2);
*n2 = 2*n1;
array_len = n1*2;
return vector2;
}
void clear_struct(void)
- {
int i;
- if(abc!=NULL){
- for(i=0;i<struct_len;i++){
free(abc[i].list);
abc[i].list=NULL;
}
struct_len = 0;
free(abc);
abc = NULL;
printf("Clear struct array successfully!");
putchar('\n');
}
- else{
printf("Already NULL\n");
}
}
// Pass dynamic struct array
struct conn *d_struct(int n1,int *n2)
- {
int i,j;
if(abc!=NULL)clear_struct();
// Allocate sturct array
abc = (struct conn*)malloc((n1+1)*sizeof(struct conn));
// Set values
- for(i=0;i<n1+1;i++){
abc[i].list = (float*)malloc((i+2)*sizeof(float));
abc[i].ind = i+1;
abc[i].length = i+2;
- for(j=0;j<i+2;j++){
abc[i].list[j] = (float)j*j+0.5;
}
}
*n2 = n1 + 1;
struct_len = n1 + 1;
return abc;
}
Fortran代码:
- module dynamic
use,intrinsic::iso_c_binding
implicit none
! Define struct
- type,bind(c)::connect
integer(c_int)::ind
type(c_ptr)::list
integer(c_int)::length
end 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 subroutine
end interface
end module
- program test
use dynamic
implicit none
real,pointer::array(:)
integer,pointer::nn
type(c_ptr)::c_array,c_struct
type(connect),pointer::conn(:)
integer::i,j,k
nullify(array)
nn=>NULL()
c_array=c_null_ptr
i = 10
j = 0
call dynamic_array(i,c_array,j)
!c_array = dynamic_array2(i,j)
write(*,*)i,j
call c_f_pointer(c_array,array,[j])
write(*,*)
write(*,*)array
c_array=c_null_ptr
c_struct = c_null_ptr
array=>null()
i = 2*2
j = 0
c_struct = dynamic_struct(i,j)
write(*,*)i,j
call 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))
enddo
call clear_struct()
call clear_array()
end program
************************************
Fortran传递动态数组到C
Fortran pass dynamic array to C
***********************************
Fortran代码:
- module f2c_dynamic
use,intrinsic::iso_c_binding
implicit none
integer(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 subroutine
end module f2c_dynamic
C代码:
#include <stdlib.h> /* malloc */
#include <stdio.h> /* 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<len; i++)
printf("%d | ", array[i]);
putchar('\n');
}
int main(int argc,char *argv[])
- {
int n1=5;
int n2=0;
int *a=NULL;
int *b=NULL;
a=allocArray(n1,&n2);
printf("********************\nC output\ninput:%d size:%d\n",n1,n2);
print_int_array(a,n2);
clearArray();
n2 = 0;
n1 = 6;
allocArray2(n1,&n2,&b);
printf("********************\nC output\ninput:%d size:%d\n",n1,n2);
print_int_array(b,n2);
clearArray();
a=NULL;
b=NULL;
return 0;
}
C和Fortran互相传递动态数组的更多相关文章
- ALLOCATE语句分配FORTRAN动态数组方法(转自http://blog.csdn.net/zhuxianjianqi/article/details/8067174)
数组的动态分配 a) 可分配数组 数组可以是静态的也可以是动态的.如果数组是静态的,则在编译时就被分配了固定的储存空间,并且直到程序退出时才被释放.程序运行时静态数组的大小不能改变.静态数组的缺 ...
- fortran常用语句--读写带注释文档、动态数组等语法
1.判断读取文档有多少行数据(文档最后的空行不计入其中): 首先在变量定义区域下方和执行语句前声明在程序中要被调用的GetFileN函数: external GetFileN 接下来在函数外部后边写上 ...
- C++中关于[]静态数组和new分配的动态数组的区别分析
这篇文章主要介绍了C++中关于[]静态数组和new分配的动态数组的区别分析,很重要的概念,需要的朋友可以参考下 本文以实例分析了C++语言中关于[]静态数组和new分配的动态数组的区别,可以帮助大家加 ...
- Delphi 的动态数组
传统的Pascal 语言其数组大小是预先确定的,当你用数组结构声明数据类型时,你必须指定数组元素的个数.专业程序员也许知道些许动态数组的实现技术,一般是采用指针,用手工分配并释放所需的内存. Delp ...
- shared_ptr和动态数组
std::shared_ptr智能指针是c++11一个相当重要的特性,可以极大地将开发者从资源申请/释放的繁重劳动中解放出来. 然而直到c++17前std::shared_ptr都有一个严重的限制,那 ...
- vc++基础班[28]---动态数组及动态链表的讲解
C++中也有相应的动态数组.动态链表.映射表的模板类,就是STL中的:vector.list.map 他们属于C++标准中的一部分,对于程序的移植性来说也是不错的,但是在MFC编程中使用 CArray ...
- [UE4]动态数组:TArray容器
为什么使用UE4提供的容器类? 如果你用过C++的STL库,你就知道STL提供了各种各样的容器/数据结构,使得你对处理很多数据的时候非常快捷高效.UE4同样也提供了类似的库,库里面的类型是以T开头的, ...
- [UE4]C 语言动态数组
在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定.对于这种问题,用静态数组的办法很难解决.为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数结合指 ...
- Java程序猿学习C++之数组和动态数组
数组: #include <iostream> using namespace std; //模板函数 template <class T> void dump(T val) ...
随机推荐
- 【洛谷日报#75】浅谈C++指针
放入我的博客食用效果更佳(有很多oi学习资料) 1.指针基础 1.引用 C++有一个东西叫引用,引用相当于给对象(如:变量)起了另一个名字,引用必须用对象初始化,一旦初始化,引用就会和初始化其的对象绑 ...
- 远程桌面mstsc关闭连接栏
在进行mstsc远程桌面连接电脑或者虚拟机的时候,总是会出现一个连接栏.虽然点左边的图钉可以自动隐藏,但是每次鼠标滑到上面的时候,还是会冒出来,这个就有点烦心了. 查了下资料,解决了这个问题. 关闭步 ...
- ubuntu卸载编译安装的软件
cd 源代码目录 make clean ./configure make make uninstall
- 给Django中的url起名字
url反转 =>reverse 1.from django.shortcuts import reverse 2. 利用reverse函数对URL名称进行反转 reverse(url名称 ...
- LeetCode(25)Reverse Nodes in k-Group
题目 Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. ...
- C#sql语句如何使用占位符
背景:在程序中,写sql语句时,可能要根据变量的值不同,SQL语句产生相应的变化.比如说存在变量StuName,根据变量值的不同,检索不同姓名的学生记录,这时需用到占位符的知识. 1,{0}占位符,代 ...
- MySQL索引与Index Condition Pushdown(二)
实验 先从一个简单的实验开始直观认识ICP的作用. 安装数据库 首先需要安装一个支持ICP的MariaDB或MySQL数据库.我使用的是MariaDB 5.5.34,如果是使用MySQL则需要5.6版 ...
- Oracle数据库之初步接触
每个Oracle数据库都是数据的集合,这些数据包含在一个或多个文件中.数据库有物理和逻辑两种结构.在开发应用程序的过程中,会创建诸如表和索引这样的结构,这些结构用于数据行的存储和查询.可以为对象的名称 ...
- Ubuntu 配置Apache虚拟目录
http://blog.csdn.net/spring21st/article/details/6589300 Ubuntu 配置Apache虚拟目录 http://blog.csdn.net/spr ...
- 大数据学习——mapreduce共同好友
数据 commonfriends.txt A:B,C,D,F,E,O B:A,C,E,K C:F,A,D,I D:A,E,F,L E:B,C,D,M,L F:A,B,C,D,E,O,M G:A,C,D ...