将 char 数组从 C++ 传递到 Fortran
passing char arrays from c++ to fortran
我在将 char 数组从 c++ 传递到 fortran (f90) 时遇到问题。
这是我的c ++文件'cmain.cxx':
#include <iostream>
using namespace std;
extern "C" int ftest_( char (*string)[4] );
int main() {
char string[2][4];
strcpy(string[0],"abc");
strcpy(string[1],"xyz");
cout << "c++: string[0] = '" << string[0] << "'" << endl;
cout << "c++: string[1] = '" << string[1] << "'" << endl;
ftest_(string);
return 0;
}
这是我的 fortran 文件,'ftest.f90':
SUBROUTINE FTEST(string)
CHARACTER*3 string(2)
CHARACTER*3 expected(2)
data expected(1)/'abc'/
data expected(2)/'xyz'/
DO i=1,2
WRITE(6,10) i,string(i)
10 FORMAT("fortran: string(",i1,") = '", a, "'" )
IF(string(i).eq.expected(i)) THEN
WRITE(6,20) string(i),expected(i)
20 FORMAT("'",a,"' equals '",a,"'")
ELSE
WRITE(6,30) string(i),expected(i)
30 FORMAT("'",a,"' does not equal '",a,"'")
END IF
ENDDO
RETURN
END
构建过程为:
gfortran -c -m64 ftest.f90
g++ -c cmain.cxx
gfortran -m64 -lstdc++ -gnofor_main -o test ftest.o cmain.o
编辑:请注意,可执行文件也可以通过以下方式构建:
g++ -lgfortran -o test ftest.o cmain.o
此外,-m64 标志是必需的,因为我运行的是 OSX 10.6。
执行"测试"的输出是:
c++: string[0] = 'abc'
c++: string[1] = 'xyz'
fortran: string(1) = 'abc'
'abc' equals 'abc'
fortran: string(2) = 'xy'
'xy' does not equal 'xyz'
在 ftest.f90 中声明大小为 4 的"字符串"和"预期"字符数组,即:
CHARACTER*4 string(2)
CHARACTER*4 expected(2)
重新编译会给出以下输出:
c++: string[0] = 'abc'
c++: string[1] = 'xyz'
fortran: string(1) = 'abc'
'abc' does not equal 'abc '
fortran: string(2) = 'xyz'
'xyz' does not equal 'xyz '
在大小为 3 的"cmain.cxx"中声明字符数组,即:
extern "C" int ftest_( char (*string)[3] );
int main() {
char string[2][3];
并恢复到 fortran 文件 (3) 中的原始大小,即:
CHARACTER*3 string(2)
CHARACTER*3 expected(2)
重新编译会给出以下输出:
c++: string[0] = 'abcxyz'
c++: string[1] = 'xyz'
fortran: string(1) = 'abc'
'abc' equals 'abc'
fortran: string(2) = 'xyz'
'xyz' equals 'xyz'
所以最后一种情况是唯一有效的情况,但在这里我为大小为 3 的 char 数组分配了 3 个字符,这意味着缺少终止的"\0",并导致"abcxyz"输出 - 这对于我的预期应用程序来说是不可接受的。
任何帮助将不胜感激,这让我发疯了!
以零结尾,而 fortran 字符串按照惯例是空格填充但大小固定的。您不应该期望能够在没有一些转换的情况下将 C 字符串传递给 fortran。
例如:
#include <algorithm>
void ConvertToFortran(char* fstring, std::size_t fstring_len,
const char* cstring)
{
std::size_t inlen = std::strlen(cstring);
std::size_t cpylen = std::min(inlen, fstring_len);
if (inlen > fstring_len)
{
// TODO: truncation error or warning
}
std::copy(cstring, cstring + cpylen, fstring);
std::fill(fstring + cpylen, fstring + fstring_len, ' ');
}
然后,您可以将其与 3 或 4 长度版本的 ftest
一起使用:
#include <iostream>
#include <ostream>
extern "C" int ftest_( char string[][4] );
void ConvertToFortran(char* fstring, std::size_t fstring_len,
const char* cstring);
int main()
{
char cstring[2][4] = { "abc", "xyz" };
char string[2][4];
ConvertToFortran(string[0], sizeof string[0], cstring[0]);
ConvertToFortran(string[1], sizeof string[1], cstring[1]);
std::cout << "c++: string[0] = '" << cstring[0] << "'" << std::endl;
std::cout << "c++: string[1] = '" << cstring[1] << "'" << std::endl;
ftest_(string);
return 0;
}
我建议按照"高性能标记"的建议在Fortran端使用ISO C绑定。 您已经在使用"外部 C"。 Fortran 2003 的 ISO C 绑定(目前在大多数 Fortran 95/部分 Fortan 2003 编译器中实现)使其成为一种独立于编译器和平台的方法。Charles Bailey描述了两种语言中字符串之间的差异。这个 Stackoverflow 问题有一个代码示例:从 C 调用 FORTRAN 子例程
如果您不想修改现有的 Fortran 代码,您可以在C++代码和现有 Fortran 代码之间编写一个"胶水"例程。 使用 ISO C 绑定在 Fortran 中编写胶水例程会更加可靠和稳定,因为这将基于语言标准的功能。
给出的例子太重量级了,只要你不想传递多个字符串,你就可以利用"隐藏"长度参数......
extern "C" void function_( const char* s, size_t len ) {
std::string some_string( s, 0, len );
/// do your stuff here ...
std::cout << "using string " << some_string << std::endl;
/// ...
}
你可以从福特兰打电话,比如
call function( "some string or other" )
你不需要对单个复制操作感到困惑,因为 std::string 构造函数可以为你完成所有这些工作。
- 使用 VS2015 在 Windows 10 上构建 Fortran .lib x64 位并将其链接到 C++
- 将 OR 逻辑运算符从 C++ 转换为 Fortran
- Fortran 和 C++ 的混合编程:Fortran 不能调用C++子程序
- 如何在C++中获取真实值精度 与Fortran相同(Pararel Studio XE编译器)
- 读取 C++ 中的 Fortran 数据类型
- 重新编译我们的FORTRAN代码并在C++中使用后,我们的system()或C_str()命令无法正常工作
- 使用C++和fortran构建R包,Mac
- 如何将C++17 stdc++fs库链接到混合语言(C++和Fortran)CMake项目
- 混合编程 - 包括C++标头到 Fortran
- 编译 Fortran 和C++程序并从英特尔编译器链接
- 与 MSVC 一起使用的 MinGW 的 Fortran 模块导致未解析的符号"__exmod_MOD_value"
- 将指向 1D Fortran 数组的指针传递给使用 C_LOC() 进行C++会导致垃圾值
- 将分配给C++数组传递给 Fortran 子例程
- 在 Fortran 中泛化特定声明类型的操作
- CPP -D 选项,用于预处理 Fortran 代码
- 通过矢量下标访问 Fortran 数组,相当于 cpp
- 如何将矢量从C 传递到Fortran
- 将字符串从 Fortran 传递到 c++
- 是否可以从C 调用FORTRAN接口
- C /FORTRAN项目由Visual Studio 2010/Intel 2013创建,将不会在Visual St