0

我正在尝试在 C 中定义和声明一组结构,然后在 fortran 中与它们进行交互,然后再将它们传递回去以在 C 函数中进行操作。我知道可以通过使用 c 结构和 fortran 通用块来实现互操作性。我尝试了几种方法都没有成功。

限制:使用 cvfortran、f77。转换为较新的格式是不现实的。对于 C,使用 MSVS C 编译器。

这是 cvfortran 手册第 618 页的建议:(http://jp.xlsoft.com/documents/intel/cvf/cvf_pg.pdf

“举个例子,假设你的 Fortran 代码有一个名为真的公共块,如图所示:”

!DEC$ ATTRIBUTES ALIAS:'Really' :: Really
REAL(4) x, y, z(6)
REAL(8) ydbl
COMMON / Really / x, y, z(6), ydbl

“您可以使用以下外部数据结构从您的 C 代码访问此数据结构:”

#pragma pack(2)
extern struct {
float x, y, z[6];
double ydbl;
} Really;
#pragma pack()

每当我尝试这个时,我都会收到“未解析的外部符号 _Really 在函数 xxx 中引用的错误,它无法编译。

CVFortran 手册中的方法:

Fortran

      PROGRAM MYPROG
      !DEC$ ATTRIBUTES ALIAS:'Really' :: Really
      REAL(4) x, y, z
      COMMON / Really / x, y, z

      INTERFACE 
          SUBROUTINE STRUCTFUN()
cDEC$ ATTRIBUTES C, ALIAS:'_StructFun' :: STRUCTFUN  ! for calling C functions
          END SUBROUTINE STRUCTFUN 
      END INTERFACE  
      X = 6.
      Y = 5.
      Z = 0.       

      CALL STRUCTFUN() 
      END PROGRAM

C

#include <stdio.h>

void StructFun(void)
{
    #pragma pack(2)
    extern struct {
    float x, y, z;
    } Really;
    #pragma pack()
    printf("x: %f\n y: %f\n z: %f\n", Really.x, Really.y, Really.z);
    printf("From C \n");

}

所以然后我尝试了我在下面粘贴的内容,其中我在头文件中定义了一个结构类型,然后尝试使它在 c 外部。我还应该提到,我将 C 函数导出为带有 .def 文件的 dll,以便可以从我的 fortran 模块中调用它。这不会产生任何错误,但会为我的所有变量返回零值。

示例程序:

Fortran

      PROGRAM MYPROG
      REAL(4) X,Y,Z
      COMMON / REALLY / X, Y, Z

      INTERFACE 
          SUBROUTINE STRUCTFUN()
cDEC$ ATTRIBUTES C, ALIAS:'_StructFun' :: STRUCTFUN  ! for calling C functions
          END SUBROUTINE STRUCTFUN 
      END INTERFACE  
      X = 6.
      Y = 5.
      Z = 0.       

      CALL STRUCTFUN() 
      END PROGRAM

C 函数


#include "structProg.h"
rtype really_;
void StructFun(void)
{
  printf("x: %f\n y: %f\n z: %f\n", really_.x, really_.y, really_.z);
  printf("From C \n");

}

C 头文件

#include <string.h>
#include <stdio.h>

typedef struct{
    float x;
    float y;
    float z;
} rtype;

extern rtype really_;
extern void StructFun(void);

我知道因为我使用的是旧编译器,所以问这个问题有点牵强,但任何指导都将不胜感激。

我也尝试过这里列出的方法:http: //www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html

4

2 回答 2

1

您更新的问题提出了与原始问题不同的问题。现在的问题是:

这不会产生任何错误,但会为我的所有变量返回零值。

那是因为您根本没有访问公共块。尽管really_在您的头文件中有对象的外部声明...

extern rtype really_;

...您的 .c 源包含对象的定义really_,原因是:

rtype really_;

从技术上讲,这是一个“暂定定义”,但是在同一个翻译单元中没有带有初始化程序的定义,指定的对象在该 TU 中定义,并使用所有成员 0 进行初始化。因此,您的 C 代码打印出来也就不足为奇了那些零。

此外,不清楚为什么您希望能够REALLY通过 name访问 Fortran 公共块really_。您从 CVF 文档中提供的具体示例和这些文档的更广泛的文本都不支持该结论。在 Fortran 端声明的块没有别名,文档让我期望它可以通过其名称的全大写版本在 C 端访问REALLY

extern struct {
    float x;
    float y;
    float z;
} REALLY;

void StructFun(void) {
    printf("x: %f\n y: %f\n z: %f\n", REALLY.x, REALLY.y, REALLY.z);
    printf("From C \n");
}

特别注意

  • C 区分大小写,而 Fortran 不区分大小写,但 CVF 文档似乎表明默认情况下它会为 Fortran 对象和函数生成大写的外部名称。
  • CVF 文档似乎也暗示它不会通过用下划线装饰 Fortran 对象的外部名称来破坏它们。(我还没有阅读足够的内容来确定这是否同样适用于子例程和函数。)
  • typedef虽然这样做并没有错,但对于公共块来说,结构类型不是必需的。不过,鉴于数据的性质,我认为不这样做似乎更自然。
  • 请注意,我的示例 C 代码仅提供对象的声明REALLY(作为外部对象),而不是定义。
  • 如果您愿意,可以将声明移动REALLY到头文件中。如果您要从多个 C 翻译单元访问它,那将是合适的,但如果您只打算在一个翻译单元中使用它,则没有必要。
  • 您也可以将您的函数声明放在头文件中,但这只有在被其他翻译单元中定义的其他 C 函数调用时才有意义。
于 2019-03-26T15:17:44.937 回答
0

我在这里不是大师,但错误表明没有集成的“C 和 Fortran”程序。

您在 Fortran 中开发一些模块,在 C (C++) 中开发一些模块。您决定它是 C 程序(然后main作为程序入口点)还是 Fortran 程序(然后它具有 Fortran 程序入口点)。

您使用各自的编译器编译 C 模块和 Fortran 模块。这些交付 .obj 或 .o 文件、目标文件。最后,您将这些链接在一起以创建可执行程序。

你所做的似乎是正确的。但是“未解析的外部符号”错误是链接器错误。这意味着链接器在目标模块中找不到 Fortran Common 块。

我希望这有帮助。

于 2019-03-26T13:54:37.707 回答