0

私は、C 関数への単一の呼び出しを追加して、巨大な Fortran 2003 プログラムを更新する必要がある C プログラマーです。

最初に、ループ カウンター (および可能であれば日付/時刻) を含む文字列を使用して C 関数を内部から正しく呼び出す最小限の Fortran ラッパー (最新の自由形式の Fortran では、シャウトなし) を作成する必要があります。ループ。

これは「簡単」なはずですが、私が行った検索では、動作するプログラムを作成するのに十分なスニペットが得られませんでした。

最近の 64 ビット バージョンの gfortran と Intel ifort コンパイラを 64 ビット Linux で使用していますが、テスト コードは両方のコンパイラを使用してコンパイルする必要があります。

ファイル send_to_port.c の C 定義は次のとおりです。

int send_to_port(int port, char *data, unsigned int length);

最後のパラメーターは、Fortran が末尾の null を気にする必要がないようにするために追加されました (私は C で処理します: data[length] = '\0';)。長さパラメーターは Fortran によって「自動的に」追加されることを理解しているため、Fortran 呼び出しには、整数のポート番号と送信する文字列の 2 つのパラメーターしかありません。

次の gfortran 行と同等の ifort を使用してコードをコンパイルしたいと考えています。

gfortran -ffree-form test.f -o test send_to_port.o

最小限のコードを探しています。約 10 ~ 20 行である必要があると考えていますが、Fortran についてはわかりません。test.f の現在の編集バッファーは次のとおりです (コンパイルされません)。

use iso_c_binding
use iso_fortran_env, stdout => output_unit
implicit none

! Fortran interface to C routine:
!   int send_to_port(int port, char *data, unsigned int length);
interface
  integter(c_int) function send_to_port(port, data) bind(C)
  integer(c_int), value :: port
  character(kind=c_char) :: data(*)
end interface

integer(c_int) retval, cnt, port
character(1024) str

cnt = 0
port = 5900

do  ! Infinite loop (^C to exit)
  call fdate(date)
  cnt = cnt + 1
  write(str, "(A,A,I8)") date, ": Iteration = ", cnt
  write(stdout, *) str  ! Show what's about to be sent
  retval = send_to_port(port, str)  ! Send it
  write(stdout, *) retval  ! Show result
  call sleep(1)
end do

end

ヘルプ?

4

2 に答える 2

1

引数の数に関する MSB のコメントに加えて、インターフェイス ブロックの構文が公開されており、インターフェイス本体のスコープに導入する必要がある項目がいくつかあります。

write ステートメントのユニットはOUTPUT_UNIT*の同義語 (そしてはるかに典型的) であるため (最小限のコードが必要な場合は、PRINT ステートメントもそのユニットに書き込みます) に注意してください。str 出力項目の周りに TRIM() を使用することもお勧めします。同様に、LEN_TRIM(str) はおそらく 3 番目の引数として渡すのに妥当な長さsend_to_portです。

自由形式の Fortran ソースの拡張子として .f を使用しないでください。代わりに .f90 を使用してください。

コードにfdateおよびへの参照が含まれていますがsleep、これらは標準の組み込み関数ではありません。これらの動作はコンパイラ間で異なる可能性があることに注意してください (問題ないと思いますが、確認する必要があります。これらの最初のものは、より移植性の高いソリューションのための適切なテキスト書式設定コードと共に DATE_AND_TIME 組み込み関数に置き換えることができます。

use, intrinsic :: iso_c_binding, only: c_int, c_char
implicit none

interface
  function send_to_port(port, data, length) bind(C)
    use, intrinsic :: iso_c_binding, only: c_int, c_char
    implicit none
    integer(c_int), value :: port
    character(kind=c_char) :: data(*)
    integer(c_int), value :: length
    integer(c_int) :: send_to_port
  end function send_to_port
end interface

integer(c_int) :: retval, port
integer :: cnt    
character(len=1024,kind=c_char) :: str
character(30) :: date

cnt = 0
port = 5900_c_int

do  ! Infinite loop (^C to exit)
  call fdate(date)
  cnt = cnt + 1
  write(str, "(A,A,I8)") trim(date), ": Iteration = ", cnt
  print *, trim(str)  ! Show what's about to be sent
  retval = send_to_port(port, str, len_trim(str))  ! Send it
  print *, retval  ! Show result
  call sleep(1)
end do
end
于 2014-09-03T04:47:04.433 に答える