我的代码的主要部分是C语言(从Python调用)。 C-part调用Fortran编写的函数。使用错误代码和带有错误描述的错误字符串传播可能的错误。
问题是我似乎无法获得正确的接口来在Fortran中编写字符串并在C中读取/复制/操作它。下面的代码概述了我想要做的事情,标记为{{1}的注释}指示需要扩展的位置。
* ... *
// 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;
}
我尝试过很多东西,但我似乎无法让它发挥作用......
答案 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可用。