Fortran: 使用和定制std::vector容器构件

Fortran使用std::vector容器

Fortran程序中需要一种类似C++ std::vector能自动增长的容器构件,网上有纯Fortran 2003实现的类似模板类,晦涩难懂,
实际需求比较简单,首要利用std::vector动态添加功能(push_back),第二是排序,第三个是可以按下标遍历容器,其他功能不需要,
而且std::vector的模板类型固定(std::tuple)

实现中用C结构封装一个指向std::vector>指针,面向对象采用C风格的函数调用,使用底层指针转发动作


C/C++端源码

//file vector_interface.cpp

#include 
#include 
#include 
#include 
#include 

using namespace std;

using IJV=std::tuple<int,int,double>; //COO
using Vector=std::vector<IJV>;

struct VectorF90{
  Vector *ptrVec;
  std::size_t hash_code;
};

using VecF=VectorF90;

extern "C"{
  
  static inline bool check_obj(const VecF *vptr)
  {
    assert(vptr->ptrVec!=nullptr);
    assert(vptr->hash_code==typeid(Vector).hash_code());

    return true;
  }
    
  void Vector_new(VecF *vptr)
  {
    vptr->ptrVec=new Vector();
    vptr->hash_code=typeid(Vector).hash_code();

    check_obj(vptr);
  }
  
  void Vector_delete(VecF *vptr)
  {
    check_obj(vptr);
    delete vptr->ptrVec;
    vptr->ptrVec=nullptr;
    vptr->hash_code=0;
  }
  
  void Vector_push(VecF *vptr,int i,int j, double value)
  {
    check_obj(vptr);
    
    auto &v=*(vptr->ptrVec);
    v.push_back(std::make_tuple(i,j,value));
 
    return;
  }
  
  void Vector_ijv(VecF *vptr, size_t idx, int *i, int *j, double *value)
  {

    check_obj(vptr);
    
    auto &v=*(vptr->ptrVec);
    *i=std::get<0>(v[idx]);
    *j=std::get<1>(v[idx]);
    *value=std::get<2>(v[idx]);
   
    return;
  }
  
  size_t Vector_size(const VecF *vptr)
  {
    check_obj(vptr);
    auto &v=*(vptr->ptrVec);
   
    return v.size();
  }

  void Vector_sort(VecF *vptr)
  {
    auto &v=*(vptr->ptrVec);
    
    std::sort(std::begin(v),std::end(v));

  }

} //extern "C"
  

用C风格函数转发vector调用


Fortran端源码和测试程序

!file: test_vector.F90
module vec_type
  use iso_c_binding
  type,bind(c)::Vector
     type(c_ptr)::ptrVec
     integer(c_size_t)::hash_code
  end type Vector

end module vec_type

module vec_mod
  interface
     !new
     subroutine Vector_new(vec) &
          &bind(c,name="Vector_new")
       use vec_type
       
       !integer(c_size_t),value,intent(in)::size
       type(Vector),intent(out)::vec
     end subroutine Vector_new

     !delete
     subroutine Vector_delete(vec) &
          &bind(c,name="Vector_delete")
       use vec_type
       type(Vector)::vec
     end subroutine Vector_delete

     !size
     function Vector_size(vec)&
       &bind(c,name="Vector_size")
       use vec_type
       type(Vector)::vec
       integer(c_size_t)::Vector_size
     end function Vector_size

     !push
     subroutine Vector_push(vec,i,j,v)&
          &bind(c,name="Vector_push")
       use vec_type
       type(Vector)::vec
       integer,value::i,j
       real*8,value::v
     end subroutine Vector_push

     !get
     subroutine Vector_get(vec,index,i,j,v)&
          &bind(c,name="Vector_ijv")
       use vec_type
       type(Vector)::vec
       integer(c_size_t),value::index
       integer::i,j
       real*8 :: v
     end subroutine Vector_get

     !sort
     subroutine Vector_sort(vec)&
          &bind(c,name="Vector_sort")
       use vec_type
       type(Vector)::vec
     end subroutine Vector_sort
     

  end interface
  
end module vec_mod


program test_vector
  use vec_mod

  call test()

  stop

contains
  subroutine test()
    use vec_type
    use vec_mod
    type(Vector) vec

    integer(c_size_t) ::size,idx

    integer::i,j
    real*8 v
    
    size=10
    
    call Vector_new(vec)
    call Vector_push(vec,0,0,1.111d0)
    call Vector_push(vec,2,1,2.d0)
    call Vector_push(vec,1,2,3.d0)
    call Vector_push(vec,1,1,2.2222d0)
    print*,Vector_size(vec)

    !sort
    call Vector_sort(vec)


    size=Vector_size(vec)

    !注意: 0-based(C)
    do idx=0,size-1
       call Vector_get(vec,idx,i,j,v)
       print*,i,j,v
    end do
    
    call Vector_delete(vec)
  end subroutine test
end program test_vector

!----------------------------------------------------------
!编译:
!   g++ -std=c++17 -c vector_interface.cpp
!   gfortran test_vector.F90 vector_interface.o -lstdc++
!
!-----------------------------------------------------------

在Fortran端声明C端对应的类型和函数接口

你可能感兴趣的:(Fortran,Fortran)