【发布时间】:2018-01-26 16:15:51
【问题描述】:
我正在开发一个通过命令行接收一些用户参数的Linux程序。
用户界面是用 C 语言制作的,数据处理是用 Fortran 语言制作的,所以 C 语言的 main 函数将一些参数传递给 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 中 main 函数的 dirpwf 指针获取正确的值,并且存储在 FileNameSize 变量中的字符串大小也是正确的,而 Fortran 理解接收到的大小(显然是 -136420716)是低于预期 (80 )。
我该如何解决这个问题?
【问题讨论】:
-
FileName的长度为 80,与FileNameSize的值无关。 -
您是否可以随意更改 Fortran 子例程,或者您是否需要使用它并让 C 很好地发挥作用?如果您可以更改 Fortran,那么 C 互操作性工具将解决您的问题(可能)。 fortran-iso-c-binding wiki 中有一些细节。
-
您的 Fortran 子程序源可能是固定格式的,因此您需要注意这里的格式。
-
例如可以看到this question。
-
如果
char *dirdat = malloc(sizeof(char)*500);中的malloc()后面跟着dirdat = argv[i+1];,则它没有意义。你所做的只是泄漏内存。而sizeof(char)根据定义始终是一。