前一篇文章讨论了C++程序对Fortran动态链接库中的函数调用,其数据交换主要在Fortran程序之间,而没有出现在两种语言之间。本文进一步探讨C++与Fortran动态链接库之间的数据交换。
数据交换有多种方式,例如通过函数的参数传递、指针、全局变量等等。C++与Fortran这两种语言之间一般变量(变量或数组等)的数据传递比较容易,但自定义数据类型的数据交换则略显困难,主要是因为两种语言对于自定义数据类型的内存管理方式存在差异。示例如下:
一、Fortran90 程序
MODULE EXAMP_MOD USE, INTRINSIC :: ISO_C_BINDING IMPLICIT NONE !两个自定义类型 TYPE,BIND(C) :: EXAMP1_TYPE REAL(C_FLOAT) :: A INTEGER(C_INT) :: I1 INTEGER(C_INT) :: I2 END TYPE EXAMP1_TYPE TYPE,BIND(C) :: EXAMP2_TYPE REAL(C_FLOAT) :: AA INTEGER(C_INT) :: II1, II2 END TYPE EXAMP2_TYPE !函数接口可以不要 !interface ! !subroutine FSUB(EXAMP,COMMON_EXAMP,INT_ARG, STR_IN, STR_OUT) bind(C,name='FSUB') !use examp_mod !implicit none !type(EXAMP1_TYPE) :: EXAMP !type(EXAMP2_TYPE) :: COMMON_EXAMP !INTEGER :: INT_ARG !CHARACTER,dimension(*):: STR_IN !CHARACTER,dimension(*) :: STR_OUT !end subroutine FSUB ! !end interface END MODULE EXAMP_MOD
在Fortran中,通过module定义了两个自定义数据类型,将这两个类型定义的变量通过函数参数,实现了C++与Fortran之间的传递。
!通过参数传递这两个自定义类型的变量 SUBROUTINE FSUB(EXAMP,COMMON_EXAMP,INT_ARG, STR_IN, STR_OUT) !BIND(C,NAME='FSUB') !如果绑定,反而对字符参数传递有影响,因为fortran当中是字符串,而C++是字符数组 !DEC$ ATTRIBUTES DLLEXPORT::FSUB USE EXAMP_MOD IMPLICIT NONE TYPE(EXAMP1_TYPE) :: EXAMP ! !DEC$ ATTRIBUTES DLLEXPORT :: vEXAMP! TYPE(EXAMP2_TYPE) :: COMMON_EXAMP ! !DEC$ ATTRIBUTES DLLEXPORT :: vCOMMON_EXAMP! INTEGER, INTENT(IN) :: INT_ARG !如果绑定应该使用INTEGER(C_INT) CHARACTER(*), INTENT(IN) :: STR_IN !如果绑定应该使用CHARACTER(C_CHAR) CHARACTER(*), INTENT(OUT) :: STR_OUT !如果绑定应该使用CHARACTER(C_CHAR) CHARACTER*5 INT_STR WRITE (INT_STR,'(I5.5)')INT_ARG !将整型数转换成字符串 EXAMP%A = 12. EXAMP%I1 = 22 EXAMP%I2 = 33 COMMON_EXAMP%AA = 13. COMMON_EXAMP%II1 = 24 COMMON_EXAMP%II2 = 34 STR_OUT = STR_IN // INT_STR // CHAr(0) !合并字符串,如果绑定此处STR_OUT = STR_IN RETURN END subroutine FSUB
二、C++程序
#include#include #include #include // 与Fortran对应的两个自定义类型 typedef struct EXAMP1_TYPE{ float A; int I1; int I2; }EXAMP; typedef struct EXAMP2_TYPE{ float AA; int II1; int II2; }COMMON_EXAMP; extern "C" void _cdecl FSUB (EXAMP *vEXAMP1, //也可使用&vEXAMP1 COMMON_EXAMP *vCOMMON_EXAMP1, //也可使用&vCOMMON_EXAMP1 int *INT_ARG, //也可使用&INT_ARG char *STR_IN, char *STR_OUT, size_t STR_IN_LEN, size_t STR_OUT_LEN);
在C++中,首先也要定义两个与Fortran对应的数据类型,同时申明外部函数,需要注意函数声明中变量的写法。
void main (int argc, char *argv[])
{
// declaration
char instring[40];
char outstring[40];
int intarg;
EXAMP vEXAMP;
COMMON_EXAMP vCOMMON_EXAMP;
// initializing
strcpy_s(instring,"Testing...");
intarg = 123;
vEXAMP.A = 0.;
vEXAMP.I1 = 0;
vEXAMP.I2 = 0;
vCOMMON_EXAMP.AA = 0.;
vCOMMON_EXAMP.II1 = 0;
vCOMMON_EXAMP.II2 = 0;
FSUB(&vEXAMP,&vCOMMON_EXAMP,&intarg,instring,outstring,strlen(instring),sizeof(outstring));
//若外部函数声明中使用了取地址符&,此处则应使用EXAMP,COMMON_EXAMP,intarg
printf(" %f %i %i %f %i %in", vEXAMP.A, vEXAMP.I1, vEXAMP.I2, vCOMMON_EXAMP.AA, vCOMMON_EXAMP.II1, vCOMMON_EXAMP.II2);
vEXAMP.A = 0.;
vEXAMP.I1 = 0;
vEXAMP.I2 = 0;
vCOMMON_EXAMP.AA = 0.;
vCOMMON_EXAMP.II1 = 0;
vCOMMON_EXAMP.II2 = 0;
printf(" %f %i %i %f %i %in", vEXAMP.A, vEXAMP.I1, vEXAMP.I2, vCOMMON_EXAMP.AA, vCOMMON_EXAMP.II1, vCOMMON_EXAMP.II2);
printf("%sn",outstring);
system("pause");
}
通过地址或值传递都可以实现两种语言之间的数据交换。程序运行结果如下:



