从fortran调用C(ifort,gfortran) [英] Calling C from fortran (ifort, gfortran)

查看:366
本文介绍了从fortran调用C(ifort,gfortran)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C程序员,必须通过向C函数添加单个调用来更新庞大的Fortran 2003程序.

I'm a C programmer who has to update a huge Fortran 2003 program by adding a single call to a C function.

首先,我需要编写一个最小的Fortran包装器(在现代的自由格式Fortran中,不要大喊大叫),它将使用包含循环计数器(以及日期/时间,如果可能的话)的字符串正确调用C函数. ,从一个循环中.

First, I need to write a minimal Fortran wrapper (in modern, free-form Fortran, no shouting) that will correctly call the C function with a string that contains a loop counter (and the date/time, if possible), from within a loop.

这应该是容易的",但是我所做的任何搜索都没有生成足以让我创建工作程序的摘录.

This should be "easy", but none of the searches I've done yielded enough snippets for me to create a working program.

我正在使用最新的64位版本的gfortran和64位Linux下的Intel ifort编译器,并且测试代码需要使用这两种编译器进行编译.

I'm using recent 64-bit versions of gfortran and the Intel ifort compiler under 64-bit Linux, and the test code needs to compile using both compilers.

这是C定义,位于文件send_to_port.c中:

Here's the C definition, in the file send_to_port.c:

int send_to_port(int port, char *data, unsigned int length);

添加了最后一个参数,以使Fortran不必担心结尾的null(我在C中处理它:data [length] ='\ 0';).我了解到长度参数是由Fortran自动"添加的,因此Fortran调用将只有两个参数,即整数端口号和要发送的字符串.

The last parameter was added to permit Fortran to have to not worry about the trailing null (I handle it in C: data[length] = '\0';). I understand the length parameter is added "automatically" by Fortran, so the Fortran call will have just two parameters, the integer port number and the string to send.

我希望使用以下gfortran行以及等效的ifort来编译代码:

I hope to compile the code with the following gfortran line, plus the equivalent for ifort:

gfortran -ffree-form test.f -o test send_to_port.o

我正在寻找最少的代码:我认为应该在10到20行左右,但是我不知道Fortran.这是我当前用于test.f的编辑缓冲区(不会编译):

I'm looking for minimal code: I'm thinking it should be around 10-20 lines, but I don't know Fortran. Here's my current edit buffer for test.f (which doesn't compile):

use iso_c_binding
use iso_fortran_env, stdout => output_unit
implicit none

! Fortran interface to C routine:
!   int send_to_port(int port, char *data, unsigned int length);
interface
  integter(c_int) function send_to_port(port, data) bind(C)
  integer(c_int), value :: port
  character(kind=c_char) :: data(*)
end interface

integer(c_int) retval, cnt, port
character(1024) str

cnt = 0
port = 5900

do  ! Infinite loop (^C to exit)
  call fdate(date)
  cnt = cnt + 1
  write(str, "(A,A,I8)") date, ": Iteration = ", cnt
  write(stdout, *) str  ! Show what's about to be sent
  retval = send_to_port(port, str)  ! Send it
  write(stdout, *) retval  ! Show result
  call sleep(1)
end do

end

帮助?

推荐答案

(是的,违背了fortran-iso-c-binding问号...)

(Yes, going against the fortran-iso-c-binding question tag...)

如果不能使iso-c-binding起作用...根据编译器版本的不同,我遇到了一些问题,我更喜欢在混合C和FORTRAN时使用原始方法: 避免接口只需为C函数创建一个包装器"即可.

If you cannot make the iso-c-binding work... As depending of the compiler version, I got some issues and i prefer going raw to the metal when mixing C and FORTRAN: avoiding interfaces simply create a "wrapper" for your C function.

包装指南大致如下:

  • 函数名称必须以_结尾(在linux上.在Windows上,函数名称必须为ALL_CAPS,且没有尾随_)

  • The function name must end with _ (on linux. on windows the function name must be ALL_CAPS with no trailing _)

如果在C ++程序中编译,请定义为extern"C"

If compiled in a C++ program, define as extern "C"

所有参数都是指针

在内存中,多维数组索引被颠倒[i] [j]为[j] [i]

In memory, multi-dimensional array indexes are reversed [i][j] is [j][i]

所以C代码是:

extern "C" 
void send_to_port_fort_(int* port, char *data, int* length, int *result)
{
  *result = send_to_port(*port,data,*length);
}

然后从fortran

Then from fortran

call send_to_port_fort(port,data,size(data),retval)

因为没有接口声明,所以没有或没有进行参数大小/类型检查或转换

Since there is no interface statement, there is no or argument size/type checking nor conversion

这篇关于从fortran调用C(ifort,gfortran)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆