Fortran程序中需要一种类似C++ std::vector能自动增长的容器构件,网上有纯Fortran 2003实现的类似模板类,晦涩难懂,
实际需求比较简单,首要利用std::vector动态添加功能(push_back),第二是排序,第三个是可以按下标遍历容器,其他功能不需要,
而且std::vector的模板类型固定(std::tuple
实现中用C结构封装一个指向std::vector
//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调用
!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端对应的类型和函数接口