将char数组从c ++传递到fortran [英] passing char arrays from c++ to fortran
问题描述
我无法将字符数组从c ++传递到fortran(f90)。
这是我的c ++文件'cmain.cxx':
#include< iostream>
using namespace std;
externCint 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(字符串)
CHARACTER * 3字符串(2)
CHARACTER * )
预期数据(1)/'abc'/
预期数据(2)/'xyz'/
DO i = 1,2
WRITE ,10)i,string(i)
10 FORMAT(fortran:string(,i1,)=',a,' ).eq.expected(i))THEN
WRITE(6,20)string(i),expected(i)
20 FORMAT(',a,'equals' ')
ELSE
WRITE(6,30)string(i),expected(i)
30 FORMAT(',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
此外,运行OSX 10.6时需要-m64标志。
执行'test'的输出是:
c ++:string [0 ] ='abc'
c ++:string [1] ='xyz'
fortran:string(1)='abc'
'abc' string(2)='xy'
'xy'不等于'xyz'
在size为4的ftest.f90中声明'string'和'expected'字符数组,即:
CHARACTER * 4 string 2)
CHARACTER * 4 expected(2)
并且重新编译给出以下输出: / p>
c ++:string [0] ='abc'
c ++:string [1] ='xyz'
fortran:string(1)='abc'
'abc'不等于'abc'
fortran:string(2)='xyz'
'xyz'不等于'xyz '
在cmain.cxx中声明大小为3的字符数组,即:
externCint ftest_(char(* string)[3]);
int main(){
char string [2] [3];
并恢复到fortran文件中的原始大小(3),即:
CHARACTER * 3 string(2)
pre>
CHARACTER * 3 expected(2)
并且重新编译提供以下输出:
c ++:string [0] ='abcxyz'
c ++:string [1] ='xyz'
fortran:string(1)='abc'
'abc'equals'abc'
fortran:string(2)='xyz'
'xyz'等于'xyz'
所以最后一种情况是唯一一个工作,但在这里我已经分配了3个字符大小为3的字符数组,这意味着终止'\0'缺失,并导致'abcxyz'输出 - 这是不可接受的为我的预期应用。
任何帮助将非常感谢,这是我的坚果!
解决方案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>
externCint 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;
}
I am having trouble passing char arrays from c++ to fortran (f90).
Here is my c++ file, '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; }
Here is my fortran file, '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
The build process is:
gfortran -c -m64 ftest.f90 g++ -c cmain.cxx gfortran -m64 -lstdc++ -gnofor_main -o test ftest.o cmain.o
Edit: note that the executable can also be build via:
g++ -lgfortran -o test ftest.o cmain.o
Also, the -m64 flag is required as I am running OSX 10.6.
The output from executing 'test' is:
c++: string[0] = 'abc' c++: string[1] = 'xyz' fortran: string(1) = 'abc' 'abc' equals 'abc' fortran: string(2) = 'xy' 'xy' does not equal 'xyz'
Declaring the 'string' and 'expected' character arrays in ftest.f90 with size 4, ie:
CHARACTER*4 string(2) CHARACTER*4 expected(2)
and recompiling gives the following output:
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 '
Declaring the character arrays in 'cmain.cxx' with size 3, ie:
extern "C" int ftest_( char (*string)[3] ); int main() { char string[2][3];
and reverting to the original size in the fortran file (3), ie:
CHARACTER*3 string(2) CHARACTER*3 expected(2)
and recompiling gives the following output:
c++: string[0] = 'abcxyz' c++: string[1] = 'xyz' fortran: string(1) = 'abc' 'abc' equals 'abc' fortran: string(2) = 'xyz' 'xyz' equals 'xyz'
So the last case is the only one that works, but here I have assigned 3 characters to a char array of size 3 which means the terminating '\0' is missing, and leads to the 'abcxyz' output - this is not acceptable for my intended application.
Any help would be greatly appreciated, this is driving me nuts!
解决方案C strings are zero terminated whereas fortran strings, by convention, are space padded but of fixed size. You shouldn't expect to be able to pass C strings to fortran without some conversion.
For example:
#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, ' '); }
Which you can then use with either the 3 or 4 length version of
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; }
这篇关于将char数组从c ++传递到fortran的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!