良い一日。おそらく私の問題の定義があまり理解できず、いくつかの不正確さがあることをお詫びします-私はプログラミングに挑戦し始めたばかりです。それでも、私はすべてをわかりやすく説明するために最善を尽くします。
私は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)を使用してどのように解析できますか?
これらはすべて非常に厄介であり、理解の漏れによるものであることに気づきましたが、これはプログラミングにおける私のほぼ最初の真剣な経験です。