gpt4 book ai didi

c++ - Fortran 从 C 接受字符串(?)

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:58:41 25 4
gpt4 key购买 nike

我觉得这应该是一个简单的问题,但我做不到。我有一些 Fortran 代码接受如下输入:

      SUBROUTINE TRACE(X,Y,NAME,XX,YY)
EXTERNAL NAME
CALL NAME(X,Y,XX,YY)

我正在尝试以以下形式从 C++ 传递一个名称:

float x,y,xx,yy;
char * name="IGRF";
trace_(&x,&y,name,&xx,&yy);

它可以编译,但是当我尝试调用 NAME 子例程时,我总是遇到段错误。文件中定义了一个名为 IGRF 的子例程,我可以直接从 C++ 调用 IGRF 子例程,但需要这个 TRACE 例程。在 gdb 中运行时,它表示 NAME 变量作为指向 void 的指针出现。

我试过传递 NAME、&NAME、&NAME[0],一个 char NAME[4],它的\0 被剥离以完全适合名称,它们都返回显示相同的 void 指针。有谁知道如何从 C++ 中获取函数名称到 Fortran 中的 EXTERNAL 变量中?

谢谢

最佳答案

因此 Fortran2003 及更高版本的优势之一是 C 互操作性被定义到标准中;使用起来有点像 PITA,但一旦完成,它保证可以跨平台和编译器工作。

所以这是 cprogram.c,调用 Fortran 例程 getstring:

#include <stdio.h>

int main(int argc, char **argv) {
int l;
char *name="IGRF";

l = getstring(name);

printf("In C: l = %d\n",l);

return 0;
}

这是fortranroutine.f90:

integer(kind=c_int) function getstring(instr) bind(C,name='getstring') 
use, intrinsic :: iso_c_binding
character(kind=c_char), dimension(*), intent(IN) :: instr
integer :: len
integer :: i

len=0
do
if (instr(len+1) == C_NULL_CHAR) exit
len = len + 1
end do


print *, 'In Fortran:'
print *, 'Got string: ', (instr(i),i=1,len)
getstring = len
end function getstring

makefile 很简单:

CC=gcc
FC=gfortran

cprogram: cprogram.o fortranroutine.o
$(CC) -o cprogram cprogram.o fortranroutine.o -lgfortran

fortranroutine.o: fortranroutine.f90
$(FC) -c $^

clean:
rm -f *.o cprogram *~

并在 gcc/gfortran 和 icc/ifort 下运行它:

 In Fortran:
Got string: IGRF
In C: l = 4

更新:哦,我刚刚意识到你正在做的事情比仅仅传递一个字符串要复杂得多;您实际上是在尝试传递一个指向 C 回调例程的函数指针。这有点棘手,因为您必须使用 Fortran interface 来声明 C 例程——仅使用 extern 是行不通的(而且无论如何都不如显式接口(interface)好,因为没有类型检查等)所以这应该有效:

c程序.c:

#include <stdio.h>

/* fortran routine prototype*/
int getstring(char *name, int (*)(int));

int square(int i) {
printf("In C called from Fortran:, ");
printf("%d squared is %d!\n",i,i*i);
return i*i;
}


int cube(int i) {
printf("In C called from Fortran:, ");
printf("%d cubed is %d!\n",i,i*i*i);
return i*i*i;
}

int main(int argc, char **argv) {
int l;
char *name="IGRF";

l = getstring(name, &square);
printf("In C: l = %d\n",l);
l = getstring(name, &cube);
printf("In C: l = %d\n",l);


return 0;
}

froutine.f90:

integer(kind=c_int) function getstring(str,func) bind(C,name='getstring')
use, intrinsic :: iso_c_binding
implicit none
character(kind=c_char), dimension(*), intent(in) :: str
type(c_funptr), value :: func

integer :: length
integer :: i

! prototype for the C function; take a c_int, return a c_int
interface
integer (kind=c_int) function croutine(inint) bind(C)
use, intrinsic :: iso_c_binding
implicit none
integer(kind=c_int), value :: inint
end function croutine
end interface
procedure(croutine), pointer :: cfun

integer(kind=c_int) :: clen

! convert C to fortran procedure pointer,
! that matches the prototype called "croutine"
call c_f_procpointer(func, cfun)

! find string length
length=0
do
if (str(length+1) == C_NULL_CHAR) exit
length = length + 1
end do

print *, 'In Fortran, got string: ', (str(i),i=1,length), '(',length,').'

print *, 'In Fortran, calling C function and passing length'
clen = length
getstring = cfun(clen)

end function getstring

结果:

$ gcc -g -Wall   -c -o cprogram.o cprogram.c
$ gfortran -c fortranroutine.f90 -g -Wall
$ gcc -o cprogram cprogram.o fortranroutine.o -lgfortran -g -Wall
$ gpc-f103n084-$ ./cprogram
./cprogram
In Fortran, got string: IGRF( 4 ).
In Fortran, calling C function and passing length
In C called from Fortran:, 4 squared is 16!
In C: l = 16
In Fortran, got string: IGRF( 4 ).
In Fortran, calling C function and passing length
In C called from Fortran:, 4 cubed is 64!
In C: l = 64

关于c++ - Fortran 从 C 接受字符串(?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5609502/

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