将char数组从c ++传递到fortran [英] passing char arrays from c++ to fortran

查看:252
本文介绍了将char数组从c ++传递到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)
CHARACTER * 3 expected(2)
pre>

并且重新编译提供以下输出:

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆