gpt4 book ai didi

c - 从Fortran 90调用用C编写的客户端程序

转载 作者:太空宇宙 更新时间:2023-11-04 00:46:18 26 4
gpt4 key购买 nike

这是this question的后续问题。
我试图从下面的Fortran 90程序调用一个用C编写的客户机。

program name
implicit none

! type declaration statements
character indata, ipaddr, ans, calc
integer portno
indata = "INDATA"
ipaddr = "localhost"
portno = 55555

! executable statements
print *, indata
ans = calc(indata, ipaddr, portno)
print *, ans

end program name

我的C程序如下
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>


/*
int main()
{
calc_("1 2 add", "localhost", 55555);
return 0;
}
*/

void error(char *msg)
{
perror(msg);
exit(0);
}

int calc_(char *indata, char *ipaddr, int *in_portno)
{
int sockfd, portno, n;

struct sockaddr_in serv_addr;
struct hostent *server;

char buffer[256];
portno = in_portno;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");

server = gethostbyname(ipaddr);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}

memset(((char *) &serv_addr), 0, (sizeof(serv_addr)));
serv_addr.sin_family = AF_INET;
memcpy(((char *)server->h_addr),
((char *)&serv_addr.sin_addr.s_addr),
(server->h_length));
serv_addr.sin_port = htons(portno);

if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");

memset((buffer), 0, (256));
strcpy(buffer, indata);
//fgets(buffer, 255, *indata);
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
memset((buffer), 0, (256));
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}

在C程序中有一个注释掉的主程序如果使用main,一切正常(运行在localhost上的服务器会回复:3,这是预期的),但是当我尝试运行上述程序时,使用makefile:
# Use gcc for C and gfortran for Fortran code.
CC=gcc
FC=gfortran

calc : calcf.o fclient.o
$(FC) -o calc calcf.o fclient.o

fclient.o : fclient.c
$(CC) -Wall -c fclient.c

calcf.o: calcf.f90
$(FC) -c calcf.f90

我把下面的错误信息打印到stdout。
 1 //[author's comment], this 1 is from the "1 2 add" printed in the .f90 program

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0 0x7fd8e9c9430f in ???
#1 0x7fd8e9d6816f in ???
#2 0x7fd8e9d59677 in ???
#3 0x400e0a in ???
#4 0x400cdd in ???
#5 0x400d81 in ???
#6 0x7fd8e9c81740 in ???
#7 0x400b68 in ???
#8 0xffffffffffffffff in ???
zsh: segmentation fault (core dumped) ./calc

我能够理解我在某种程度上访问受限内存,或者程序不应该修改的内存,但我无法看到这是在哪里发生的,以及为什么只有当我从.f90程序调用 calc_时才会出现这种情况。

最佳答案

在Fortran 2003引入C互操作功能之前,从Fortran调用外部C函数需要特定于目标环境和所涉及的编译器的技巧此外,如果所讨论的C函数不是专门设计为可由所涉及的Fortran编译器生成的代码调用的,那么通常需要编写一个包装函数(用C语言)来弥合这一差距。
要克服的主要问题是
名称管理:Fortran源代码中引用函数的名称通常与链接器必须链接的名称不同通常会引入一个或多个附加下划线,并且通常会将函数名放入标准大小写中(通常为小写,但有些编译器使用大写)。
参数类型:有些Fortran参数类型根本无法干净地传递,至少在没有相关Fortran实现的详细知识的情况下是这样假定的形状数组、数组节和具有allocatablepointer属性的数组通常是有问题的。
类型表示:这里最大的一个是数组索引顺序Fortran数组按列主顺序编制索引,而C数组按行主顺序编制索引这不一定是传递数组的问题(但也请参见上面的内容);相反,在调用的一边和另一边正确使用数组是一个问题这里的另一个重要特点是Fortrancharacter对象(字符串)不以空结尾相反,每个值都有一个固定长度,包含在值表示中。这通常通过传递两个实际参数(一个指向char数组开头的指针和一个长度)在C函数接口上进行调整,但也使用了其他形式。
函数调用语义:Fortran通过引用传递所有参数。它通常显示为一个C函数接口,其中的参数都是指针,除了上面描述的字符串长度参数(因为Fortrancharacter对象有固定的宽度)。
参数顺序:Fortran可调用的C函数通常使用与Fortran端调用预期使用的参数顺序相同的参数顺序,但这是不保证的,而且无论如何,字符串长度的参数都不能完全适应这种情况。一些Fortran编译器在相应指针之后立即传递它们;另一些则在参数列表的末尾将所有字符串长度参数分组(当然,这并不考虑那些使用完全不同的机制来表示字符串参数的情况。)
可以想象,我忽略了一些事情。
几乎所有这一切都有实质性的实现依赖性,但是人们从Fortran 90诞生之前就一直在Fortran和C之间来回调用,而且他们还在继续这样做如果您没有可以依赖的标准化C互操作的好处,那么您需要了解Fortran编译器如何生成代码的一些细节有各种各样的自动化工具可以实现这一点,包括在GNU Autoconf中,或者您可以查阅文档,甚至进行实验。
值得一提的是,您似乎有几个问题,有些在上面描述的领域,有些完全在Fortran部分在Fortran部分中特别值得注意的是,您没有为character变量声明长度,因此它们都得到默认长度(1)这显然不是你想要的在函数调用时,Fortran不使用以空结尾的字符串,并为字符串长度传递额外的参数,这也会使您出错。
但是Fortran 2003已经有13年的历史了,C互操作位被广泛实现,包括在gfortran中,Makefile显示这是Fortran的实现gfortran文档覆盖了C interop相当彻底对于这个已经冗长的答案来说,有太多了,但关键点包括:
用自然C写出C部分。
使用ISO_C_BINDING模块。
向C函数编写Fortraninterface,适当地定义形式参数和返回类型,包括适当的属性(从kind提供的参数值中提取)
ISO_C_BINDING属性应用于必须与C互操作的符号

关于c - 从Fortran 90调用用C编写的客户端程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37923144/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com