传播错误字符串:Fortran> C

时间:2015-09-22 06:51:36

标签: c fortran

问题陈述

我的代码的主要部分是C语言(从Python调用)。 C-part调用Fortran编写的函数。使用错误代码和带有错误描述的错误字符串传播可能的错误。

问题是我似乎无法获得正确的接口来在Fortran中编写字符串并在C中读取/复制/操作它。下面的代码概述了我想要做的事情,标记为{{1}的注释}指示需要扩展的位置。

C

* ... *

的Fortran

// global variable: read from Python if an error is encountered
char* error_string;

// template for the Fortan-subroutine
void fortran_calculation_( double* , int* );


int heavy_calculation( double* x )
{

  int error_code;


  // ... some code ...


  // * should accept and write "error_string" *
  fortran_calculation_( x , &error_code );

  if ( error_code ) 
  {
    error_string = "TO BE WRITTEN BY FORTRAN > REMOVE!!";
    return 1;
  }


  // ... some code ...


  return 0;

}

我尝试过很多东西,但我似乎无法让它发挥作用......

2 个答案:

答案 0 :(得分:4)

你有两个问题。一,如何从Fortran访问C全局变量。这个相对简单,在iso_c_binding模块中创建一个接口。有关示例,请参阅https://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Global-Variables.html

然而,棘手的问题是你已经将你的error_string定义为char的指针。这意味着您的Fortran代码必须在写入之前分配字符串。 Fortran可分配和指针变量使用描述符,而不是原始指针,因此您必须首先创建C malloc函数的接口。只有在那之后你才能写信给它。类似的东西:


module my_error_string
  use iso_c_binding
  interface
     type(c_ptr) function c_malloc(size) bind(C, name="malloc")
       use iso_c_binding
       integer(kind=c_size_t), value :: size
     end function c_malloc
  end interface
  type(c_ptr), bind(C) :: error_string

contains
  subroutine write_error(str)
    character(len=*) :: str
    character, pointer :: fstr(:)
    integer(c_size_t) :: strlen
    integer :: i

    strlen = len(str, kind=c_size_t) + 1_c_size_t
    error_string = c_malloc(strlen)
    if (.not. c_associated(error_string)) then
       call perror("error_string is a null pointer => malloc failed?!")
       stop 1
    end if
    call c_f_pointer(error_string, fstr, shape=[strlen])
    do i = 1, len(str)
       fstr(i) = str(i:i)
    end do
    fstr(strlen) = c_null_char
  end subroutine write_error
end module my_error_string

(更改接口可能很简单,以便您将已分配的C字符串传递给Fortran函数以填充,或者可能使用回调函数。但上述工作,如果这是您想要的。)

答案 1 :(得分:2)

这是一个可耻的丑陋"解决方案"根据您提供的设计解决您的问题。

main.c中:

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

char error_string_[512];

void fortan_calculation_( double*, int*, int* );

int main() {
   double d = 2.5;
   int l, i = 3;
   memset( error_string_, 0, 512 );

   fortan_calculation_( &d, &i, &l );
   error_string_[l] = 0;
   printf( "After call: '%s'\n", error_string_ );

}

error.f90:

subroutine fortan_calculation( d, i, l )
    implicit none
    character(512) str
    common /error_string/ str
    double precision d
    integer i, l

    str = "Hello world!"
    l = len_trim( str )
end subroutine fortan_calculation

编译和测试:

$ gcc -c main.c
$ gfortran -c error.f90
$ gcc main.o error.o -lgfortran
$ ./a.out 
After call: 'Hello world!'

但这只是令人恶心的代码:它假定了很多(可以说是)Fortran编译器的常见做法,而它存在一些使用iso_c_binding Fortran模块正确连接C和Fortran的方法。

我会看一下,看看我能否提出一个正确的解决方案。

编辑:实际上,nice SO page about that可用。