2012-02-24 9 views
0

良い日です。申し訳ありませんが、おそらく私の問題の定義といくつかの不正確な定義 - 私はちょうどプログラミングで自分自身を試し始めている。それでも、私はすべてを明白に説明するために最善を尽くします。C-Fortran文字列の相互運用性

私はFortranで書かれた数学的なDLLを持っています。

たとえば、機能があります。この関数は、ログファイルの名前をdllに解析して計算を監視するために使用されます。

integer function initLog(
*       int_parameter, 
*       char_parameter, 
*       char_parameter_length, 
*      ) 
*bind(C, name = "initLog"); 
    use, intrinsic :: ISO_C_BINDING; 
    !DEC$ATTRIBUTES DLLEXPORT::initLog 

    integer(C_INT),   value :: parameter; 
    character(C_CHAR), intent(in) :: char_parameter(char_parameter_length); 
    integer(C_INT),   value :: char_parameter_length; 

    ... 

    some_other_variable = char_parameter(1:1)(1:char_parameter_length); 

    end function; 

通常、私はMATLABを使用してdllを処理します。したがって、MATLABから直接関数を呼び出すには.mexファイルを使用する必要があります。 .mexファイルの中には、MATLABとdllの間のインターフェイスを提供するC言語で書かれたインターフェイスコードがあります。例えば、前述の機能のためのCインタフェースは次のとおりです。

int doSmth(const int int_parameter, 
      const char* char_parameter, 
      const int char_parameter_length,); 

そして私は、機能を得るために、LoadLibrary関数とGetProcAddressなどを使用しています。そして、これはうまく動作します。

しかし、今私はdllを使用するFortranで.exeテストファイルを作成する必要があります。だから、私はDLLをimport.libライブラリにリンクすることによってexeにリンクしなければなりません。この実行可能ファイルの別のオプションは、ログファイルの名前をパラメータとしてコマンドライン経由で取得することです。

program test 
    use dll_name; 
    use ifport; 
    implicit none; 
    ... 
    integer :: log_init_status; 
    ... 
    log_init_status = init_log(2, 'logfile.log', len('logfile.log')); 
    ... 
end program 

このリリースでは正常に動作しますが、「深刻なを返す(664):範囲外:サブストリング終了位置 "だから、最初に私はこのように、単にexeファイル内からログファイルのファイル名を渡そうとしました11 'が文字列長さ' 1 '"よりも大きいです。しかし、最初はこのバグは見つからず、コードを書いていました。これは私が今持っているものです:

program test 
    use dll_name; 
    use ifport; 
    use ISO_C_BINDING; 
    implicit none; 
    ... 
    character*255  :: log_flag_char; 
    integer(C_INT) :: log_flag; 
    character*255  :: filename; 
    character(C_CHAR) :: log_filename; 
    integer(C_INT) :: log_filename_length; 

    .... 

    call getarg(5, log_flag_char); 
    read(log_flag_char, *) log_flag; 

    call getarg(6, log_filename); 
    log_filename_length = len(log_filename); 

    log_init_status = analyticsLogInit(log_flag, log_filename, log_filename_length); 

    ... 

end program 

これはうまくいきましたが、LOG_FILENAMEの唯一の1最初の文字を取った( "C:\ ABCD \ logfile.log" "C" に変換されます)。私が変更した場合

文字(C_CHAR):: log_filename;

に文字(C_CHAR):: LOG_FILENAME(255);

私はlog_filenameの長さが255です(トリムで固定することもできます)。そして、2番目の - mainは再び "severe(664):Out範囲の:部分文字列終了位置 '255'は文字列長 '1'より大きい。

私が変更した場合

log_init_status = analyticsLogInit(log_flag、LOG_FILENAME、 log_filename_length)。

log_init_status = analyticsLogInit(log_flag、C_LOC(LOG_FILENAME)、 log_filename_length)に

のように、実際のものとは異なる仮引数型に関するエラーが発生します。

示す664エラーがDLL内のこの行から来ていることを私は自分自身が感じている:

some_other_variable = char_parameter(1:1)(1:char_parameter_length)。

。私は私のexeのような何かを書く必要があります

文字* 255 :: log_filename;

なく

文字:: LOG_FILENAME(255);

しかし、どのように(C_CHAR)を使用して解析することができますか?

私はこれがすべて厄介であり、それはすべて理解の漏れから来ていることを認識していますが、これはプログラミングにおける私の最初の深刻な経験です。

答えて

2

私はあなたの質問に目を通しましたが、注意しなければならないのは、character変数または名前付き定数が宣言される方法です。長さと種類の2種類のパラメータを指定できます。宣言で対応するキーワードを使用しない場合、最初のパラメータは長さを指定し、2番目のパラメータ(存在する場合)は種類を指定します。あなたが使用したものである

character(len=255, kind=C_CHAR) :: log_filename 
character(255, kind=C_CHAR)  :: log_filename 
character(255, C_CHAR)   :: log_filename 
character(kind=C_CHAR, len=255) :: log_filename 
character(kind=C_CHAR)   :: log_filename*255 

一方、次の構文(:
あなたは長さ255と種類C_CHARの文字変数を宣言したいのであれば、あなたは次のいずれかの方法で行うことができます)、値C_CHARcharacter変数を宣言します。

character(C_CHAR) :: log_filename 

ああ、次の構文は、255個の要素、長C_CHARの文字変数である各素子のアレイを宣言する。

character(C_CHAR) :: log_filename(255) 

だから、結論は1つがFortranで文字エンティティを宣言するの特殊性を研究するためにいくつかの時間を取る必要があること、です。

+0

ありがとうございます。確かに、私のためにFortranで研究されるべきことがたくさんあることを理解しています。それでも、文字と(C_CHAR):: log_filename "の構文は、整数と倍精度で動作するので、正常に動作することを確信していました(と私が読んだ記事に書かれていたので) – AntalOvc

+0

悲しいかな、"文字(C_CHAR) "文字(kind = C_CHAR)"は何も与えませんでした。また、今私は "some_other_variable = char_parameter(1:1)(1:char_parameter_length);" "文字(C_CHAR)、intent(in):: char_parameter(char_parameter_length);"として宣言されている場合に機能します。 – AntalOvc