2017-06-27 20 views
1

C++コードをFortranに適用するには、次の例(http://fortranwiki.org/fortran/show/Fortran+and+Cpp+objects)に従っています。まず、Fortranを学習し、FortranとC++間の接続を試みています。FortranからC++への文字列の受け渡し

私は、私は、FortranからC++

#include <iostream> 
#include <string> 

using namespace std; 
class CWLiDAR { 
    string name; 

public: 
    CWLiDAR(string); 
}; 


CWLiDAR::CWLiDAR(string name) 
{ 
    this->name = name; 
} 


/* 
*/ 

/* C wrapper interfaces to C++ routines */ 
#ifdef __cplusplus 
extern "C" { 
#endif 
CWLiDAR* CWLiDAR__new(string name) 
{ 
    return new CWLiDAR(name); 
} 
void CWLiDAR__delete(CWLiDAR* This) 
{ 
    delete This; 
} 
#ifdef __cplusplus 
} 
#endif 

Fortranのラッパー

module CWLiDAR_module 
    use, intrinsic :: ISO_C_Binding!, only: C_int, C_ptr, C_NULL_ptr 
    implicit none 
    private 
    type CWLiDAR_type 
    private 
    type(C_ptr) :: object = C_NULL_ptr 
    end type CWLiDAR_type 
    interface 
    function C_CWLiDAR__new (name, name_len) result(this) bind(C, name = "CWLiDAR__new") 
     import 
     type(C_ptr) :: this 
     character(name_len, kind=C_CHAR), intent(IN) :: name 
     integer :: name_len 
    end function C_CWLiDAR__new 
    subroutine C_CWLiDAR__delete (this) bind(C, name = "CWLiDAR__delete") 
     import 
     type(C_ptr), value :: this 
    end subroutine C_CWLiDAR__delete 
    end interface 
    interface new 
    module procedure CWLiDAR__new 
    end interface new 
    interface delete 
    module procedure CWLiDAR__delete 
    end interface delete 
    public :: new, delete, CWLiDAR_type 
contains 


! Fortran wrapper routines to interface C wrappers 
    subroutine CWLiDAR__new(this, name, name_len) 
    type(CWLiDAR_type), intent(out) :: this 
    character(*) :: name 
    integer :: name_len 
    this%object = C_CWLiDAR__new(name, name_len) 
    end subroutine CWLiDAR__new 
    subroutine CWLiDAR__delete(this) 
    type(CWLiDAR_type), intent(inout) :: this 
    call C_CWLiDAR__delete(this%object) 
    this%object = C_NULL_ptr 
    end subroutine CWLiDAR__delete 
end module CWLiDAR_module 

メイン

program main 
    use cwlidar_module 
    type(CWLiDAR_type) :: lidar 
    call new(lidar, "Test", 4) 

    call delete(lidar) 
end program main 

どのように修正する必要がありますに文字列を渡したいコードを修正FortranからC++に文字列を渡すためのFortranラッパー?

+0

変更するFortranラッパーはどれですか?どのように?彼らは正しいと思われる。彼らは正しいのですか?どのように? –

+0

[FortranからCへの文字列を返す](https://stackoverflow.com/a/44424572/7038689)を参照してください。 –

+0

なぜこれが重複としてマークされているのか分かりません - この質問はFortranからC++に渡すことに関するものであり、リンクされた疑わしい重複はC++からFortranに渡すことです。 – carthurs

答えて

1

まず、std::stringをFortranとCの間のインターフェイスで使用することはできません。std::stringは、Fortranとの相互運用性のためのメモリレイアウトが保証されていないC++実装定義オブジェクトです。

代わりにプレーンC文字列を使用する必要があります。だから、CVLiDAR__new()はタイプchar*の引数を受け入れる必要があり、およびFortranインターフェイスは、Fortranラッパールーチンは、いくつかのFortran character仮引数を取り、適切に割り当てられたcharacter(kind = c_char)にその内容をコピーするために進まなければなら

character(kind = c_char) :: name(*) 

として、この引数を宣言しなければなりません配列は、次にC関数に渡されます。

この時点で、Cインターフェイス関数は、C++ std::stringに再度変換することができます。この変換はオプションで、C++はC言語だけでなくC言語も処理できます。変換を追加することで、残りのコードはC++にすることができます。

C文字列をFortran側でアセンブルするときに、ゼロ文字で正しく終了させることを忘れないでください!


これらの引数の変換は確かに面倒くさされている、とあなたがFortranのから呼び出す必要があるインターフェイス機能の任意の数を持っている場合、Fortranラッパーを発生する発電機のスクリプトを記述することをお勧めします。このようなスクリプトの例は、cdi-1.8.1/interfaces/f2003/bindGen.rbファイルのClimate Data Interfaceライブラリ(CDI、ソースコードはhttps://code.mpimet.mpg.de/projects/cdi/filesにあります)内にあり、その出力はcdi-1.8.1/src/mo_cdi.f90の下に同じtar-ballで公開されています。このスクリプトはあなたのケースでは完璧すぎるかもしれませんが、CDIで非常にうまく動作します。その出力は、あなたのコンバージョンを正しく行う方法のアイデアを得るのに役立ちます。

+0

私はCスタイルの文字列がこの種の目的に必要であることに同意しますが、それはOPが 'std :: string'を使用できないということを意味するものではありません。 'std :: string'は最適化され、標準的で、C++では' char * 'よりも親しみやすく、' c_str() '関数は' std :: string'からCスタイルの文字列に変換することができます。それを利用する? (注:自動的にヌルターミネータを付加する)(結果として生じるCスタイルの文字列にはhttps://stackoverflow.com/a/7416473/5209610)。ヌル終了出力を望まない場合は、 'data()'関数を使用してください。 –

+0

@VladislavMartin私はあなたの意見を参照してください、あまりにも不正確で申し訳ありません。私はあなたのC++コードで 'std :: string'を使うことはできないとは決して言いませんでしたが、Fortran-Cインターフェースでは使えないと言っていました。私は今私の答えをもっと明確に更新しました。 – cmaster

0

FortranからC++ string(実際にはstd::string)を渡すことはできません。 CまたはFortranとの互換性がないため、内部C++型です。 Cラッパーを使用し、C互換の文字配列を渡す必要があります。

関連する問題