fortran66のブログ

fortran について書きます。

【メモ帳】ZMQ fortran binding OO化

ZMQ fortran OO 化

Fortran 2008 で行くつもりでしたが、TYPE(*) を使ったので Fortran 2018 かもしれません。

ZMQ ガイドブックのイントロ紹介の通信パターン例が何通りか出来るようになりました。

例:REP-REQ パターン

REQuest - REPly と名称上の類似を取っていて、意味的には対称性が悪いように思います。

他にも PUBlisher - SUBscriber パターンとか。

github.com

function は純粋、そうでないものは subroutine という伝統に従って、subroutine 主体にしてみました。

他の言語の書き換えを考えると、どうかとも思い、迷いましたが・・・

gfortran の final 処理中の print 文は、プログラム終了時は標準出力されないようです。しかし、ストールしないので、解放処理はちゃんとされているのではないかと思います。 finalize されていないようです。

block ... end block でくくって、ブロック内部で context や socket を宣言することで、ブロック脱出時に finalizer を呼び出すことにしました。

[追記] intel fortran だと allocatable にして、順序通りに deallocate しないとストールしていまうぅっ!!allocate - deallocate 方式にしました。

allocatable にして、deallocate してもいいのですが、使う前に allocate する必要も出てくるし~

コンストラクタを書いての代入は、また別の問題があるし~

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

oo_req.f90

program req
    use, intrinsic :: iso_c_binding
    use f08_zmq
    implicit none
    integer(c_int) :: ilen
    character(10), target :: buffer, word

    type(context_t), allocatable :: context
    type(socket_t) , allocatable :: requester

    allocate(context, requester)
    call context%new()
    call requester%new(context, ZMQ_REQ)
    call requester%connect('tcp://localhost:5555')
    call requester%send('Hello',  5, 0, ilen)
    call requester%recv(buffer, 10, 0, ilen)
    print *, trim(buffer(:ilen))

    deallocate(requester)
    deallocate(context)
end program req
hp8@HP8:~/f08_zmq/guidebook$ ./oo_req
 World
 zmq_close                 0 Resource temporarily unavailable
 zmq_ctx_destroy           0 Resource temporarily unavailable
hp8@HP8:~/f08_zmq/guidebook$

oo-rep.f90

program rep
    use, intrinsic :: iso_c_binding
    use f08_zmq
    implicit none
    integer :: ilen
    character(10), target :: buffer
    type(context_t), allocatable :: context
    type(socket_t) , allocatable :: responder

    allocate(context, responder)
    call context%new()
    call responder%new(context, ZMQ_REP)
    call responder%bind('tcp://*:5555')
    do
        call responder%recv(buffer, 10, 0, ilen)
        print *, 'Received Hello'
        call sleep(1) ! non-standard POSIX
        call responder%send('World', 5, 0, ilen)
    end do

    deallocate(responder)
    deallocate(context)
end program rep
hp8@HP8:~/f08_zmq/guidebook$ ./oo_rep
 Received Hello
 Received Hello
^C
hp8@HP8:~/f08_zmq/guidebook$