

Linux系OSでFortranを主とするアプリケーションを開発しています。
この中から（/etc/syslog.conf等の設定に従って）/var/log/messages等にメッセージを書き込みたい、
換言すると、syslogdに向けてメッセージを送りたいと考えています。 そこで以下の(1)(2)(3)のどれかに解答をいただけないでしょうか。

(1) libcのsyslogまたはvsyslogと相当の機能のあるサブルーチンで、Fortranから呼び出せるものはあるか。

(2)
Fotranから、libcのsyslogまたはvsyslogを呼び出すことは可能か。できることなら可変引数としたい。ただし、messageのフォーマットはC風の"%d\n"などでもかまわない。

(3) (1)(2)以外の方法で実現する方法はあるか。

前提として、OSはRedHat系Linux。リモート（ネットワーク越し）の利用は考慮しない。
要すればCのコードを混在させることは可能だが、あくまでもFotranコードのエラー等を出力することが目的である。
ある程度の速度性能が欲しい（ゆえに、call system("...") は不可とする）。 Fortranの処理系は、Intel Fortran
Compilerの最新版が使用できるものとする。

以上です。


CC BY-SA 3.0
2014-12-22T10:57:19.367
2382
2015-01-10T08:36:20.063
2014-12-22T11:39:20.520
208
question
linux fortran
Fortranからsyslogメッセージを書き込む方法


FORTRANに*.oをリンクして呼び出すことができるのでそれを利用されてはどうでしょうか？
ご存知かと思いますが、FORTRANとCで文字列をやりとりする場合、形式が違うので気をつけてください。

以下にサンプルを書いてみました。

<https://github.com/magicdrive/FORTRAN_SYSLOG_SAMPLE>


CC BY-SA 3.0
2014-12-24T14:41:36.380
2505
2014-12-24T14:41:36.380
5684
2382
answer


Intel Fortran Compiler(以後 ifort)はlibcの関数を直接呼び出せます。  
ifortからC関数を呼び出すポイントは以下の2点です。  
(1) interface文でC関数の引数のスタックへの積み方の規則や引数の型を指定する。  
(2) C関数呼び出し時に(1)の指定に従って引数を渡す。(値渡しをしたい場合は`%val()`を使用します)

以下は`puts()`と`isdigit()`を呼び出すサンプルプログラムです。

[code]

    module libc_api
        use iso_c_binding
        implicit none
    
        interface
            integer(c_int) function puts(s) bind(c, name='puts')
                use, intrinsic :: iso_c_binding
                character(c_char), dimension(*), intent(in) :: s
            end function puts
    
            integer(c_int) function isdigit(c) bind(c, name='isdigit')
                use, intrinsic :: iso_c_binding
                integer(c_int), intent(in) :: c
            end function isdigit
        end interface
    end module libc_api
    
    program main
        use libc_api
        implicit none
    
        character(64, c_char) str
        integer(c_int) ret
        integer(c_int) cint
    
        ! call c-api puts()
        str = "hello world."c
        ret = puts(str)
        print '("puts() ret: ",i0)', ret
    
        ! call c-api isdigit() - 1
        cint = ichar('7')
        ret = isdigit(%val(cint))
        print '("isdigit(''",a1,"'') ret: ",i0)', cint, ret
    
        ! call c-api isdigit() - 2
        cint = ichar('f')
        ret = isdigit(%val(cint))
        print '("isdigit(''",a1,"'') ret: ",i0)', cint, ret
    end program main
    
[/code]

コンパイル:

[code]

    $ ifort hige.f90
    
[/code]

実行結果:

[code]

    $ ./a.out
    hello world.
    puts() ret: 13
    isdigit('7') ret: 2048
    isdigit('f') ret: 0
    
[/code]

* * *

本題の`syslog()`呼び出しですが可変引数ですので、interface文で`ATTRIBUTES VARYING`指定をします。  
(これを指定するとコンパイル時に引数の型チェックがおこなわれなくなるので注意が必要です)

[code]

    module libc_api
        use iso_c_binding
        implicit none
    
        interface
            subroutine syslog(pri,fmt) bind(c, name='syslog')
                !dir$ attributes varying :: syslog
            end subroutine syslog
        end interface
    end module libc_api
    
    program main
        use libc_api
        implicit none
    
        integer(c_int) cint
    
        ! call c-api syslog()
        cint = 12345
        call syslog(%val(3), "write from fortran. cint:%d\n"c, %val(cint))
        call syslog(%val(3), "%s %s, %d\n"c, "hello"c, "world"c, %val(cint))
    end program main
    
[/code]

上記コードをビルドして実行し`/var/log/messages`に以下のメッセージが書かれていることを確認しました。

[code]

    Jan 10 17:01:47 system7 a.out: write from fortran. cint:12345
    Jan 10 17:01:47 system7 a.out: hello world, 12345
    
[/code]

コード中のキーワードや「C 互換性保持」「ATTRIBUTES C and STDCALL」を  
インテル® Fortran コンパイラー 15.0 ユーザー・リファレンス・ガイドでキーワード検索すると関連する情報に辿り着けると思います。

* * *

動作確認環境:  
OS: fedora19 (64bit), GNU libc 2.17  
Fortranコンパイラ環境: インテル® Parallel Studio XE Professional Edition for Fortran
(評価版) for Linux

[code]

    $ ifort --version
    ifort (IFORT) 12.1.3 20120212
    
[/code]

その他: fedora19ではsyslogdが動いていなかったので`yum install syslog-ng`しました。


CC BY-SA 3.0
2015-01-10T08:36:20.063
4366
2015-01-10T08:36:20.063
2687
2382
answer