0

良い一日。おそらく私の問題の定義があまり理解できず、いくつかの不正確さがあることをお詫びします-私はプログラミングに挑戦し始めたばかりです。それでも、私はすべてをわかりやすく説明するために最善を尽くします。

私は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を使用する.exeテストファイルをFortranで作成する必要があります。したがって、インポート.libライブラリにリンクしてdllをexeにリンクする必要があります。この実行可能ファイルのもう1つのオプションは、コマンドラインからログファイルの名前をパラメーターとして取得することです。したがって、最初に、次のように、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):範囲外:サブストリングの終了位置「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」に変換されます)。変えたら

character(C_CHAR):: log_filename;

character(C_CHAR):: log_filename(255);

、2つの問題が発生します。1つ目はlog_filenameの長さが255に等しい(ただしトリムで修正できます)、2つ目は-そしてメイン-再び「重大(664):範囲外:部分文字列の終了位置「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)を使用してどのように解析できますか?

これらはすべて非常に厄介であり、理解の漏れによるものであることに気づきましたが、これはプログラミングにおける私のほぼ最初の真剣な経験です。

4

1 に答える 1

2

私はあなたの質問を一瞥しただけですが、注意すべきことの1つは、character変数または名前付き定数の宣言方法です。長さと種類の2つのタイプパラメータを指定できます。宣言で対応するキーワードを使用しない場合、最初のパラメーターは長さを指定し、2番目のパラメーター(存在する場合)は種類を指定します。
したがって、長さ255および種類の文字変数を宣言する場合C_CHARは、次のいずれかの方法で宣言できます。

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

一方、次の構文(使用した構文)は、値が何であれcharacter、長さの変数を宣言します。C_CHAR

character(C_CHAR) :: log_filename

ああ、次の構文は255要素の配列を宣言します。各要素は長さの文字変数ですC_CHAR

character(C_CHAR) :: log_filename(255)

したがって、結論は、Fortranで文字エンティティを宣言することの特性を研究するために少し時間がかかるはずであるということです。

于 2012-02-24T23:31:50.343 に答える