将字符串参数从C传递到Fortran子例程的问题

时间:2018-01-26 16:15:51

标签: c linux string fortran

我正在开发一个Linux程序,它通过命令行接收一些用户参数。

用户界面是用C语言编写的,数据处理是在Fortran中,因此C语言中的主要功能将一些参数传递给Fortran子程序。其中一些参数是字符串,我们遇到了问题。 以下是代码的一些部分:

C主要功能:

extern void anaconv_(char *FileName,int *n,char *PlanName,int *m,char *TipoDados,char *FrontName,int *l,char *Dirdat, int *h, bool *kvuge, bool *ch_serie, bool *ch_shuntb, bool *simulacao);
void ajuda_anaconv(void);

int main (int argc, char **argv)
{
  int  i;
  int  n,m,l,h;
  bool flagk     = 0;
  bool flags     = 0;
  bool flagp     = 0;
  bool flagsimul = 0;
  char *dirpwf     = malloc(sizeof(char)*80);
  char *dirbar     = malloc(sizeof(char)*80);
  char *dirfro     = malloc(sizeof(char)*80);
  char *dirdat     = malloc(sizeof(char)*500);
  char *tpdados    = malloc(sizeof(char));
  ...
  dirpwf  = argv[i+1];
  i++;
  ...
  dirbar  = argv[i+1];
  i++;
  ...
  dirfro  = argv[i+1];
  i++;
  ...
  dirdat  = argv[i+1];
  i++;
  ...
  tpdados = argv[i+1];
  i++;
  ...
  n = strlen(dirpwf)
  m = strlen(dirbar)
  l = strlen(dirfro)
  h = strlen(dirdat)
  ...
  anaconv_(dirpwf,&n,dirbar,&m,tpdados,dirfro,&l,dirdat,&h,&flagk,&flags,&flagp,&flagsimul);
  ...
  free(dirpwf);
  free(dirbar);
  free(dirfro);
  free(dirdat);
  free(dirdatcomp);
  free(tpdados);
  ...
  return 1;
}

他们,Fortran子程序就像:

SUBROUTINE ANACONV
 +(FileName,FileNameSize,PlanName,PlanNameSize,TpData,FrontName,FrontNameSize,Dirdat,DirdatSize,kVUGE,CHSERIE,CHSHUNTB,SIMUL)

    IMPLICIT NONE
    CHARACTER*80  FileName,PlanName,FrontName
    CHARACTER*500 Dirdat        
    INTEGER*4     FileNameSize,PlanNameSize,FrontNameSize,DirdatSize
    CHARACTER*1   TpData
    LOGICAL*1     kVUGE,CHSERIE,CHSHUNTB,SIMUL
    ...
END SUBROUTINE ANACONV

编译器是gcc版本4.8.5 20150623,我在CentOS Linux版本7.3.1611中运行该程序。

虽然代码编译没有问题,但是当我运行程序传递一些参数时,我收到以下消息:

Fortran runtime error: Actual string length is shorter than the declared one for dummy argument 'filename' (-136420716/80)

我试图找到用gdb调试的问题,但是我找不到错误。 FileName字符串从C中主函数的dirpwf指针获取正确的值,并且FileNameSize变量中存储的字符串大小也正确,而Fortran知道接收的大小(显然-136420716)低于预期(80)。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

Fortran和C以不同方式跟踪字符串长度。 C在末尾使用NUL字符作为终结符,而Fortran则分别保持长度。 Fortran如何做到这一点取决于实现。对于调用Fortran过程,大多数编译器会查找在命名过程之后作为附加参数传递的长度,作为按值传递的地址大小的整数。但这不是普遍的,也不是便携式的。你已经通过了这些长度,但是在字符串地址之后立即这样做了 - 这不是gfortran想要的地方。

Fortran 2003引入了C互操作性功能,允许您以可移植的方式混合使用Fortran和C. Fortran 2008有所扩展,Fortran 2018扩展了它。不幸的是,即使在F2018中,将字符串从C传递到Fortran仍然很混乱。

有人可能会认为简单的解决方案是将BIND(C)添加到Fortran子例程标头中 - 这会告诉Fortran不要使用隐藏的参数等。但是,不允许使用CHARACTER * 80等。

最简单的解决方法是将n,m,l和h移动到C调用中参数列表的末尾,删除大小的Fortran参数,并使n,m,l和h size_t而不是int。另外,不要使用&通过他们。这仍然是不可携带的,但它现在可以帮助您。

相关问题