Fortran 将字符*81 数组传递给 c/c++ 代码
fortran pass character*81 array to c/c++ code
我是编程新手,我想在我的 C++ 代码中调用 Fortran 函数。问题是我不知道如何将 Fortran 字符 *81 数组传递给我的 C++。
fortran 代码如下:
subroutine func01(a)
implicit none
character*81 a(2)
write(*,*) a(1)
write(*,*) a(2)
end
c++ 代码如下:
#include <iostream>
extern "C"{
void func01_( const char **a );
}
int main()
{
const char *a[2];
a[0]="Hello world!";
a[1]="This is a test!";
func01_(a);
return 0;
}
我使用这个
基本测试了我的 Fortran 代码
program pro01
character*81 a(2)
a(1)='Hello world!'
a(2)='This is a test!'
call func01(a)
end program pro01
'func01(a)'效果很好。
感谢@PaulMcKenzie,我纠正了一些愚蠢的问题......
然而,当我编译 cpp 代码时,结果就像乱码一样:
7
@L
@��n��@�UH�j��FP
@��n���U�շ�=��U�ྼ��� @��
我该怎么办?
以下代码似乎适用于 Linux(x86_64) 上的 gcc4,但不清楚是否对其他平台也有效。 (如上所述,现代 Fortran 的 C 语言互操作性可能会有用。)
func01.f90
subroutine func01( a )
character(*) :: a( 2 )
print *
print *, "char length = ", len(a(1)), len(a(2))
print *, "raw a(1) : [", a(1), "]"
print *, "raw a(2) : [", a(2), "]"
print *, "trim : [", trim(a(1)), "] [", trim(a(2)), "]"
end
main.cpp
extern "C" {
void func01_( char *c, const int len );
}
#include <iostream>
#include <cstring> // for memset()
int main()
{
const int lenmax = 30, numstr = 3; // changed char length to 30 to fit in the terminal
char a[ numstr ][ lenmax ];
std::string str[ numstr ];
str[0] = "moon"; str[1] = "mercury"; str[2] = "jupiter";
for( int k = 0; k < numstr; k++ ) {
memset( a[k], ' ', lenmax ); // fill space
str[k].copy( a[k], lenmax ); // copy at most lenmax char (no [=11=] attached)
}
func01_( a[0], lenmax );
func01_( a[1], lenmax ); // pass from mercury
return 0;
}
编译
$ g++ func01.f90 main.cpp -lgfortran
结果
char length = 30 30
raw a(1) : [moon ]
raw a(2) : [mercury ]
trim : [moon] [mercury]
char length = 30 30
raw a(1) : [mercury ]
raw a(2) : [jupiter ]
trim : [mercury] [jupiter]
这是一个可移植的解决方案,可将任意长度的字符串数组从 C 传递到 Fortran。
我使用了一个与你自己的非常相似的 C++ 文件:
#include <iostream>
extern "C" void func01(const char **a);
int main()
{
const char *a[2] = {"Hello World","This is a test"};
func01(a);
return 0;
}
上面唯一的变化是字符数组的初始化和删除了 Fortran 函数的不那么便携的下划线。相反,我们将使用 Fortran 2003 提供的标准 C 互操作性。func01
的 Fortran 实现变为:
subroutine func01(cstrings) bind(C,name="func01")
use, intrinsic :: iso_c_binding, only: c_ptr, c_char, c_f_pointer
implicit none
type(c_ptr), dimension(2), target, intent(in) :: cstrings
character(kind=c_char), pointer :: a1(:), a2(:)
! size_t strlen(char * s);
interface
function strlen(s) bind(C, name='strlen')
use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t
implicit none
type(c_ptr), intent(in), value :: s
integer(c_size_t) :: strlen
end function strlen
end interface
call c_f_pointer(cstrings(1), a1, [strlen(cstrings(1))])
call c_f_pointer(cstrings(2), a2, [strlen(cstrings(2))])
write (*,*) a1
write (*,*) a2
end subroutine func01
bind
属性为我们提供了与 C 的函数名称互操作性,并且我们使用 C 类型作为变量。变量 cstrings
将采用 2 个指针的数组,或者在 C 中,*[2]
或 **
。该过程的大部分是一个接口块,它允许我们调用标准 C 库例程 strlen
,通过以下对 c_f_pointer
的调用使我们的生活更轻松,它将 C 指针转换为 Fortran 指针。
编译后运行,输出如预期的那样:
$ ./string-array-test
Hello World
This is a test
使用 gcc 5.1.0 编译和测试。
我是编程新手,我想在我的 C++ 代码中调用 Fortran 函数。问题是我不知道如何将 Fortran 字符 *81 数组传递给我的 C++。
fortran 代码如下:
subroutine func01(a)
implicit none
character*81 a(2)
write(*,*) a(1)
write(*,*) a(2)
end
c++ 代码如下:
#include <iostream>
extern "C"{
void func01_( const char **a );
}
int main()
{
const char *a[2];
a[0]="Hello world!";
a[1]="This is a test!";
func01_(a);
return 0;
}
我使用这个
基本测试了我的 Fortran 代码program pro01
character*81 a(2)
a(1)='Hello world!'
a(2)='This is a test!'
call func01(a)
end program pro01
'func01(a)'效果很好。
感谢@PaulMcKenzie,我纠正了一些愚蠢的问题......
然而,当我编译 cpp 代码时,结果就像乱码一样:
7
@L
@��n��@�UH�j��FP
@��n���U�շ�=��U�ྼ��� @��
我该怎么办?
以下代码似乎适用于 Linux(x86_64) 上的 gcc4,但不清楚是否对其他平台也有效。 (如上所述,现代 Fortran 的 C 语言互操作性可能会有用。)
func01.f90
subroutine func01( a )
character(*) :: a( 2 )
print *
print *, "char length = ", len(a(1)), len(a(2))
print *, "raw a(1) : [", a(1), "]"
print *, "raw a(2) : [", a(2), "]"
print *, "trim : [", trim(a(1)), "] [", trim(a(2)), "]"
end
main.cpp
extern "C" {
void func01_( char *c, const int len );
}
#include <iostream>
#include <cstring> // for memset()
int main()
{
const int lenmax = 30, numstr = 3; // changed char length to 30 to fit in the terminal
char a[ numstr ][ lenmax ];
std::string str[ numstr ];
str[0] = "moon"; str[1] = "mercury"; str[2] = "jupiter";
for( int k = 0; k < numstr; k++ ) {
memset( a[k], ' ', lenmax ); // fill space
str[k].copy( a[k], lenmax ); // copy at most lenmax char (no [=11=] attached)
}
func01_( a[0], lenmax );
func01_( a[1], lenmax ); // pass from mercury
return 0;
}
编译
$ g++ func01.f90 main.cpp -lgfortran
结果
char length = 30 30
raw a(1) : [moon ]
raw a(2) : [mercury ]
trim : [moon] [mercury]
char length = 30 30
raw a(1) : [mercury ]
raw a(2) : [jupiter ]
trim : [mercury] [jupiter]
这是一个可移植的解决方案,可将任意长度的字符串数组从 C 传递到 Fortran。
我使用了一个与你自己的非常相似的 C++ 文件:
#include <iostream>
extern "C" void func01(const char **a);
int main()
{
const char *a[2] = {"Hello World","This is a test"};
func01(a);
return 0;
}
上面唯一的变化是字符数组的初始化和删除了 Fortran 函数的不那么便携的下划线。相反,我们将使用 Fortran 2003 提供的标准 C 互操作性。func01
的 Fortran 实现变为:
subroutine func01(cstrings) bind(C,name="func01")
use, intrinsic :: iso_c_binding, only: c_ptr, c_char, c_f_pointer
implicit none
type(c_ptr), dimension(2), target, intent(in) :: cstrings
character(kind=c_char), pointer :: a1(:), a2(:)
! size_t strlen(char * s);
interface
function strlen(s) bind(C, name='strlen')
use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t
implicit none
type(c_ptr), intent(in), value :: s
integer(c_size_t) :: strlen
end function strlen
end interface
call c_f_pointer(cstrings(1), a1, [strlen(cstrings(1))])
call c_f_pointer(cstrings(2), a2, [strlen(cstrings(2))])
write (*,*) a1
write (*,*) a2
end subroutine func01
bind
属性为我们提供了与 C 的函数名称互操作性,并且我们使用 C 类型作为变量。变量 cstrings
将采用 2 个指针的数组,或者在 C 中,*[2]
或 **
。该过程的大部分是一个接口块,它允许我们调用标准 C 库例程 strlen
,通过以下对 c_f_pointer
的调用使我们的生活更轻松,它将 C 指针转换为 Fortran 指针。
编译后运行,输出如预期的那样:
$ ./string-array-test
Hello World
This is a test
使用 gcc 5.1.0 编译和测试。