从fortran调用c ++ sub时运行时中止 [英] the run time aborting when calling c++ sub from fortran
问题描述
我在这里阅读了许多有关使用Fortran和C ++混合语言的文章.但是,我仍然遇到当前的问题:我的Fortran程序总是中止.
I had read many posts here about mixing languages use of Fortran and C++. However, I'm still stuck with my current problem: my Fortran program always aborted.
我有Fortran程序:test-cc.f90和C ++程序:deb_cc.cc.
I have the Fortran program: test-cc.f90 and the C++ program: deb_cc.cc.
deb_cc.cc包含:
deb_cc.cc contains:
#include <iostream>
using namespace std;
extern "C" void deb_cc_(float*** rh,int* x, int* y , int* z_ext )
{
cout <<"thinkdeb 1"<<endl;
int i, j, k;
cout <<"thinkdeb 1"<<endl;
cout <<"thinktest i=8,j=4,k=1"<< " (*x) " << (*x)<<endl;
cout <<"thinktest i=8,j=4,k=1"<< " x3/rh " << rh[1][1][1]<<endl; //abortion
// here
cout <<"thinkdeb 7"<<endl;
return;
}//end function
test-cc.f90包含:
test-cc.f90 contains:
use ISO_C_BINDING
implicit none
interface
subroutine deb_cc( rh,x,y,z_ext)
use ISO_C_BINDING
implicit none
real(c_float),allocatable::rh(:,:,:)
integer(c_int):: x,y,z_ext
end subroutine
end interface
integer nx,ny,nz
parameter (nx=10,ny=10,nz=10)
real ,dimension (:,:,:),allocatable:: x1
integer:: iy1,iy2,iy3,iy4
integer i,j,k
allocate(x1(nx,ny,nz))
do k=1,nz
do j=1,ny
do i=1,nx
x1(i,j,k)=k*1000+j*100+i
enddo
enddo
enddo
iy1=nx
iy2=ny
iy3=nz
call deb_cc(x1,iy1,iy2,iy3)
end
我用pgf90 -c test-cc.f90
和pgcpp -c deb_cc.cc
编译了它们
最后,我通过pgf90 -pgcpplibs test-cc.o deb_cc.o
链接了它们.
输出为:
I compiled them by pgf90 -c test-cc.f90
and pgcpp -c deb_cc.cc
Finally, I linked them by pgf90 -pgcpplibs test-cc.o deb_cc.o
.
The output is:
thinktest in test- x1 (8,2,2) is 2208.000
thinkdeb 1
thinkdeb 1
thinktest i=8,j=4,k=1 (*x) 10
Segmentation fault (core dumped)
推荐答案
您使用了iso_c_binding
模块,但是您的过程接口不可与C互操作.
You use the iso_c_binding
module, but your procedure interface is not C interoperable.
iso_c_binding
模块不是最重要的. bind(C)
属性是关键.(我曾多次抱怨标签的不幸名称)
The iso_c_binding
module is not the most important thing. The bind(C)
attribute is the key. (I ranted several times about the unfortunate name of the tag here)
您使用假定的形状可分配数组参数
You use an assumed shape allocatable array argument
real(c_float),allocatable::rh(:,:,:)
在Fortran 2008中的互操作过程中不允许使用这些,因为C或C ++不知道如何处理它们.它们不仅仅是地址.如果您在界面中使用了bind(C)
属性,则编译器应告诉您这是错误的.
these are not allowed in interoperable procedures in Fortran 2008, because C or C++ have no idea what to do with them. They are not just addresses. If you used the bind(C)
attribute in the interface, the compiler should tell you it is wrong.
可以使用特殊的C标头在下一个Fortran标准(实际上是在现有的TS中)中传递它们,但是某些编译器(尤其是gfortran)仍然不兼容.
There is a possibility to pass them in the next Fortran standard (in an existing TS actually) using a special C header, but some compilers (notably gfortran) are still not compatible.
由于您没有在C端进行任何重新分配(至少在您的示例中),因此您可以将数组作为假定的大小(array(*)
)参数传递.我还更改了C ++名称,不需要下划线.
As you do not do any reallocation on the C side (at least in your example), you can just pass the array as an assumed size (array(*)
) argument. I also changed the C++ name, no need for the underscore.
interface
subroutine deb_cc(rh,x,y,z_ext) bind(C, name="deb_cc")
use ISO_C_BINDING
real(c_float) :: rh(*)
integer(c_int):: x,y,z_ext
end subroutine
end interface
在C端,您不能使用C数组,它们是指向指针([i] [j] [k])的指针.您从Fortran收到的是一个内存块.您还必须传递数组形状.至少在前两个Fortan维度中.
On the C side, you cannot use the C arrays which are pointers to pointers ([i][j][k]). What you receive from Fortran is a single block of memory. You also have to pass the array shape. At least in the first two Fortan dimensions.
我只会使用宏在C中对数组进行索引.
I would just use a macro to index the array in C.
// adjust as needed, many variants possible
#define IND(i,j,k) = i + (j-1) * nx + (k-1) * nx * ny
// adjust as needed, many variants possible
extern "C" void deb_cc(float *rh, int *nx, int *ny, int *nz) {
cout <<"thinktest i=8,j=4,k=1"<< " x3/rh " << rh(IND(8,4,1))<<endl;
}
这篇关于从fortran调用c ++ sub时运行时中止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!