妙传C / C ++数组Fortran和返回数组计算 [英] Pass arrays from C/C++ to Fortran and return a calculated array
问题描述
我想从C / C ++的数组传递到一个Fortran 2003的模块,并获得计算值回C / C ++。我已经能够传递和返回单个值(标量)就好了,但得到的的阵列的来回被证明是困难的。我发现在标值的多个线程,我已经成功地使这些工作。
我后,我的工作的标量函数建模我的基于阵列的功能。
我用gcc / gfortran。
这里的Fortran语言模块(ConvertUnitsLib.f03)。
模块ConvertUnitsLib使用:: ISO_C_BINDING!对于C / C ++的互操作
实(c_double),BIND(C):: degF,摄氏度公共DegCtoF包含!
!转换温度摄氏度华氏
!
实(KIND = c_double)函数DegCtoF(摄氏度)结果(degF)及
&安培; BIND(C,名字=DegCtoF) 实(c_double),意图(中),尺寸(:) ::摄氏度
实(c_double),尺寸(尺寸(摄氏度)):: degF 做I = 1,大小(摄氏度)
degF(ⅰ)=(摄氏度(ⅰ)* 1.8)+ 32
做到底最终功能DegCtoF
!模块的结束
前端模块ConvertUnitsLib
和C / C ++,(CFort.cpp)
的#include<&stdio.h中GT;#IFDEF __cplusplus
为externC{
#万一
双DegCtoF(双* []);
#IFDEF __cplusplus
}
#万一
/ ******************* ********************* /
INT主(INT ARGC,CHAR *的argv [])
{
的printf(C / C ++和Fortran一起\\ n!); 双DegreesC [2] = {32,64};
双DegreesF [2]; DegreesF = DegCtoF(安培; DegreesC);
的printf(%3.1F [C] =%3.1F [F] \\ n,DegreesC,DegreesF); 返回0;
}
和最后但并非最不重要的,在Makefile
#C ++指令
CC = G ++
CFLAGS = -std = C ++ 11#Fortran指令
FC = gfortran
FFLAGS = -std = F2003所有:干净
$(FC)$(FFLAGS)-c -fcheck =所有ConvertUnitsLib.f03
$(CC)$(CFLAGS)-c CFort.cpp
$(FC)$(FFLAGS)ConvertUnitsLib.o CFort.o -o转换清洁:
RM -f *的.o
RM -f *的.mod
在francescalus证实了这一点,我会说,从我知道这是一个有点老了,互操作性不允许你正在尝试做的使用数组。
此外,编码当一些良好的生活习惯总是至关重要的。例如,使用隐无
在FORTRAN强制所有变量的声明在使用之前。使用命名常量时,语言允许,例如 2
您使用在FORTRAN数组的大小。
以下是您的code的修改版本,它应该做的事情像你想要达到的目标。
// Fortran语言
模块ConvertUnitsLib使用:: ISO_C_BINDING!对于C / C ++的互操作
!实(c_double),BIND(C):: degF,摄氏度
隐无公共DegCtoF包含!
!转换温度摄氏度华氏
!
子程序DegCtoF(摄氏度,degF,正)及
BIND(C,名字=DegCtoF) 整数,意图(中)::ñ
实(c_double),意图(中),尺寸(N)::摄氏度
实(c_double),意图(出),尺寸(N):: degF
整数::我 做I = 1,N
degF(ⅰ)=(摄氏度(ⅰ)* 1.8)+ 32
做到底结束子程序DegCtoF
// C ++
的#include<&stdio.h中GT;#IFDEF __cplusplus
为externC{
#万一
双DegCtoF(双[],双[],const int的*);
#IFDEF __cplusplus
}
#万一
/ ******************* ********************* /
INT主(INT ARGC,CHAR *的argv [])
{
const int的N = 2;
的printf(C / C ++和Fortran一起\\ n!); 双DegreesC [N] = {32,64};
双DegreesF [N]; DegCtoF(DegreesC,DegreesF,&安培; N);
的for(int i = 0; I< N;我++){
的printf(%d个:%3.1F [C] =%3.1F [F] \\ n,我,DegreesC [I],DegreesF [I]);
} 返回0;
}
I am trying to pass an array from C/C++ into a Fortran 2003 module and get the calculated values back into C/C++. I've been able to pass and return single values (scalars) just fine, but getting an array back and forth is proving difficult. I've found many threads on scalar values and I've been successful at making those work.
I've modeled my array based functions after my working scalar functions.
I am using gcc/gfortran.
Here's the Fortran module (ConvertUnitsLib.f03).
module ConvertUnitsLib
use :: iso_c_binding ! for C/C++ interop
real(c_double), bind(c) :: degF, degC
public DegCtoF
contains
!
! Convert temperature degrees Celsius Fahrenheit
!
real(kind = c_double) function DegCtoF(degC) result(degF) &
& bind(c, name = "DegCtoF")
real(c_double), intent(in), dimension(:) :: degC
real(c_double), dimension(size(degC)) :: degF
do i = 1, size(degC)
degF(i) = ( degC(i) * 1.8 ) + 32
end do
end function DegCtoF
! End of module
end module ConvertUnitsLib
And the C/C++, (CFort.cpp)
#include <stdio.h>
#ifdef __cplusplus
extern"C" {
#endif
double DegCtoF(double *[]);
#ifdef __cplusplus
}
#endif
/**********************************************************************/
int main(int argc, char *argv[])
{
printf("C/C++ and Fortran together!\n");
double DegreesC[2] = {32, 64};
double DegreesF[2];
DegreesF = DegCtoF(&DegreesC);
printf("%3.1f [C] = %3.1f [F]\n", DegreesC, DegreesF );
return 0;
}
And last but not least, the Makefile
# C++ directives
CC=g++
CFLAGS=-std=c++11
# Fortran directives
FC=gfortran
FFLAGS=-std=f2003
all: clean
$(FC) $(FFLAGS) -c -fcheck=all ConvertUnitsLib.f03
$(CC) $(CFLAGS) -c CFort.cpp
$(FC) $(FFLAGS) ConvertUnitsLib.o CFort.o -o convert
clean:
rm -f *.o
rm -f *.mod
Before francescalus confirms it, I was going to say that from what I know that was a little bit old, the interoperability does not permit what you are trying to do with arrays.
In addition, some good habits are always critical when coding. For example using implicit none
in fortran to force the declaration of all variables before they are used. The use of named constant when the language permits it, for example the 2
that you are using as array size in fortran.
Below is a modified version of your code that should do something like what you want to achieve.
//Fortran
module ConvertUnitsLib
use :: iso_c_binding ! for C/C++ interop
!real(c_double), bind(c) :: degF, degC
implicit none
public DegCtoF
contains
!
! Convert temperature degrees Celsius Fahrenheit
!
subroutine DegCtoF(degC, degF, n)&
bind(c, name = "DegCtoF")
integer, intent(in) :: n
real(c_double), intent(in), dimension(n) :: degC
real(c_double), intent(out), dimension(n) :: degF
integer :: i
do i = 1, n
degF(i) = ( degC(i) * 1.8 ) + 32
end do
end subroutine DegCtoF
// C++
#include <stdio.h>
#ifdef __cplusplus
extern"C" {
#endif
double DegCtoF(double [], double [], const int *);
#ifdef __cplusplus
}
#endif
/**********************************************************************/
int main(int argc, char *argv[])
{
const int N = 2;
printf("C/C++ and Fortran together!\n");
double DegreesC[N] = {32, 64};
double DegreesF[N];
DegCtoF(DegreesC, DegreesF, &N);
for(int i = 0; i<N; i++){
printf("%d : %3.1f [C] = %3.1f [F]\n", i, DegreesC[i], DegreesF[i] );
}
return 0;
}
这篇关于妙传C / C ++数组Fortran和返回数组计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!