zoukankan      html  css  js  c++  java
  • Python调用C/Fortran混合的动态链接库--中篇

    接下来,介绍一个简单的例子,从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代码:

     1 #! /usr/bin/env python
     2 #coding=utf-8
     3 
     4 '''
     5 A short example of use ctypes and numpy to call fortran dynamic library
     6 example for 1d struct array pass or access
     7 '''
     8 import numpy as np
     9 from numpy.ctypeslib import load_library,ndpointer
    10 from ctypes import c_int
    11 
    12 #define struct as same sa fortran
    13 abc = np.dtype([("nam",'S80',1),("val",'f4',10)])
    14 #load dynamic library
    15 flib = load_library("libexample",".")
    16 #function handle of ex01
    17 fun01 = flib.ex01
    18 #define input arguments
    19 fun01.argtypes = [ndpointer('f4'),ndpointer(abc),c_int]
    20 #
    21 n1,n2 = 5,np.array(0,'i4')
    22 vec = np.zeros((n1,),'f4')
    23 student = np.empty((n1*2,),abc)
    24 #print vec
    25 fun01(vec,student,n1)
    26 #print student
    27 #function handle of ex02_1
    28 fun02_1 = flib.ex02_1
    29 fun02_1.argtypes = [ndpointer('f4'),c_int,ndpointer('i4')]
    30 fun02_1(vec,n1,n2)
    31 #print n1,n2
    32 #function handle of ex02_2
    33 fun02_2 = flib.ex02_2
    34 fun02_2.argtypes = [ndpointer(abc),c_int]
    35 student2 = np.empty((n2,),abc)
    36 fun02_2(student2,n2)
    37 print student2

    编译命令:

    gfortran test.f90 -fPIC -shared -o libexample.so
  • 相关阅读:
    截取nginx日志
    wampserver安装之后无法打开localhost
    wampserver安装之后无法打开localhost
    wampserver安装之后无法打开localhost
    wampserver安装之后无法打开localhost
    gitlab给用户添加提交到主干的权限
    动手为王 | Oracle 数据库跨版本升级迁移实践
    ie8关于@font-face无效的兼容问题
    web自定义中文字体
    django 前后台交互过程
  • 原文地址:https://www.cnblogs.com/pasuka/p/3972711.html
Copyright © 2011-2022 走看看