妙传C / C ++数组Fortran和返回数组计算 [英] Pass arrays from C/C++ to Fortran and return a calculated array

查看:258
本文介绍了妙传C / C ++数组Fortran和返回数组计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆