Python调用C/Fortran混合的动态链接库--中篇
2014-09-15 14:09
399 查看
接下来,介绍一个简单的例子,从fortran中传递并返回一维自定义结构体数组到python
注意点:
1、fortran新标准支持可分配数组作为变量传入并在subroutine或function分配后返回;
2、BIND不支持传入可分配数组(也即1和2无法同时使用);
3、fortran没有垃圾自动回收机制;
综合上述3点,利用ctypes调用fortran不能也不宜直接返回形状大小在计算前无法确定的数组,折衷的办法是:
a、估算出返回数组的大小,可以适当偏大;
b、在fortran的module定义全局可分配数组,第一次调用后存储结果并返回数组形状数值,在python中利用numpy开辟空数组,再次调用fortran得到结果并清空fortran中module的全局变量
fortran代码:
python代码:
编译命令:
注意点:
1、fortran新标准支持可分配数组作为变量传入并在subroutine或function分配后返回;
2、BIND不支持传入可分配数组(也即1和2无法同时使用);
3、fortran没有垃圾自动回收机制;
综合上述3点,利用ctypes调用fortran不能也不宜直接返回形状大小在计算前无法确定的数组,折衷的办法是:
a、估算出返回数组的大小,可以适当偏大;
b、在fortran的module定义全局可分配数组,第一次调用后存储结果并返回数组形状数值,在python中利用numpy开辟空数组,再次调用fortran得到结果并清空fortran中module的全局变量
fortran代码:
module sam use,intrinsic::iso_c_binding implicit none type,bind(C)::abc !Define struct character(len=80)::nam real(c_float)::val(10) end type ! Global variable in fortran module ! Notice: dealloacte after using to avoid memory leak type(abc),allocatable::stu(:) contains subroutine calc(input,output,n1)bind(c,name='ex01') ! Example 01 ! Both in and out variables has assumed shape ! Bind(C) not allowed pass alloctable variables ! Pure Fortran2008 allows pass alloctable array to subroutine to allocate or deallocate implicit none integer(c_int),intent(in),value::n1 real(c_float),intent(in)::input(n1) type(abc),intent(out)::output(2*n1) integer::i do i=1,size(output) output(i)%nam = "abcdefea" output(i)%val(1:5) = real(i-1,4) output(i)%val(6::1) = i*2.5E0 enddo return end subroutine subroutine calc2(input,n1,n2)bind(c,name='ex02_1') ! Example 02_1 ! Return result's shape implicit none integer(c_int),intent(in),value::n1 real(c_float),intent(in)::input(n1) integer(c_int),intent(out)::n2 integer::i,j call clear() if(input(1)<1.E0)then allocate(stu(10)) else allocate(stu(int(input(1))+1)) endif do i=1,size(stu) stu(i)%nam = "daefvdefefadfad" do j=1,size(stu(i)%val) stu(i)%val(j) = i*j*1.5E0 enddo enddo n2 = size(stu) return end subroutine subroutine getdata(output,n)bind(c,name='ex02_2') ! Example 02_2 ! Return result and do clear implicit none integer(c_int),intent(in),value::n type(abc),intent(out)::output(n) output = stu call clear() return end subroutine subroutine clear() implicit none if(allocated(stu))deallocate(stu) end subroutine end module program test use sam implicit none real(c_float)::array(5) type(abc)::student(5*2) integer::i array = [5.E0,4.E0,6.E0,1.E0,7.E0] call calc(array,student,5) do i=1,size(student) write(*,*)student(i)%nam,student(i)%val enddo end program
python代码:
#! /usr/bin/env python #coding=utf-8 ''' A short example of use ctypes and numpy to call fortran dynamic library example for 1d struct array pass or access ''' import numpy as np from numpy.ctypeslib import load_library,ndpointer from ctypes import c_int #define struct as same sa fortran abc = np.dtype([("nam",'S80',1),("val",'f4',10)]) #load dynamic library flib = load_library("libexample",".") #function handle of ex01 fun01 = flib.ex01 #define input arguments fun01.argtypes = [ndpointer('f4'),ndpointer(abc),c_int] # n1,n2 = 5,np.array(0,'i4') vec = np.zeros((n1,),'f4') student = np.empty((n1*2,),abc) #print vec fun01(vec,student,n1) #print student #function handle of ex02_1 fun02_1 = flib.ex02_1 fun02_1.argtypes = [ndpointer('f4'),c_int,ndpointer('i4')] fun02_1(vec,n1,n2) #print n1,n2 #function handle of ex02_2 fun02_2 = flib.ex02_2 fun02_2.argtypes = [ndpointer(abc),c_int] student2 = np.empty((n2,),abc) fun02_2(student2,n2) print student2
编译命令:
gfortran test.f90 -fPIC -shared -o libexample.so
相关文章推荐
- Python调用C/Fortran混合的动态链接库--上篇
- C++调用Fortran程序----动态链接方式
- VC与Matlab混合编程之调用动态链接库dll(C++)——<二>
- C++调用Fortran程序----动态链接方式
- 【Python】Python通过ctypes调用C动态链接库
- C语言编写DLL动态链接库并分别用VB和Python调用
- Python调用C/Fortran混合的动态链接库-下篇
- 用python调用C的动态链接库
- ctypes: 使用python调用C编写的动态链接库
- python 调用so dll动态链接库
- C#调用Fortran的动态链接库的注意事项
- 枚举进程及其调用动态链接看(进程快照)
- c#中如何调用vc++写的动态链接库
- 在SQL中调用动态链接库中的函数
- jnative在linux下对c程序的动态链接库的调用问题及解决方案
- WR中调用MFC的动态链接库全过程
- C#调用C++动态链接库中的函数指针与函数指针结构
- linux下动态链接问题(.so文件的编写与调用)
- 动态链接库的显式调用
- VC调用Delphi制作的动态链接库如何互相传递字符串