Open3
Ribbon: FFIに対応する^2
これガチのマジで面倒だな。。
とりあえず、ライブラリ情報のポインタを拾ってくるところまでは実装した。一旦遅延解決、動的bindingで実装する方向で行こう。。
ライブラリ (yuni compat nccc)
を追加した。Ribbonはバイトコードコンパイラの都合で全てのプリミティブはbootstrap時に使用されていなければならないので、とりあえず (rvm-primitives)
ライブラリにもダミーのexportを追加している。
長さの無いbytevector
Ribbonでは有限長のbytevectorに加えて無限長のbytevectorを扱えるようにしてみた。 ...が、ちょっとバグってたので直した。
Ribbonは一度確保したbytevectorのアドレスが変化しないことが保証されているので、このような無限長のbytevectorを仮定できると、任意のポインタをbytevectorと見做せる。
他所のScheme処理系ではあんまり一般的でない概念なので、どこかのタイミングで変えちゃうかもしれない。。
ここまでの対応で、とりあえず NCCC の関数をlookupして呼ぶところまではできた。
とりあえず呼べるようになった
(import (yuni scheme) (yuni nccc core))
(nccc-init-embedded-bundle!)
(let ((miniio_ioctx_create (nccc-lookup 'miniio 'miniio_ioctx_create))
(miniio_ioctx_process (nccc-lookup 'miniio 'miniio_ioctx_process))
(miniio_timer_create (nccc-lookup 'miniio 'miniio_timer_create))
(miniio_timer_start (nccc-lookup 'miniio 'miniio_timer_start))
(miniio_get_events (nccc-lookup 'miniio 'miniio_get_events)))
(let* ((ctx (miniio_ioctx_create))
(timer (miniio_timer_create ctx 1))
(r (miniio_timer_start ctx timer 1000 2000))
(evtbuf (make-bytevector (* 8 128)))
(buf-writecnt (make-bytevector 4))
(buf-currentcnt (make-bytevector 4)))
(write ctx) (newline)
(unless (= r 0)
(error "Couldn't start timer" r))
(let loop ()
(let ((r (miniio_ioctx_process ctx)))
(write (list 'PROCESS: r)) (newline))
(let ((r (miniio_get_events ctx (bytevector->address evtbuf) 128
(bytevector->address buf-writecnt)
(bytevector->address buf-currentcnt))))
(let ((written (bv-ref/u32 buf-writecnt 0))
(current (bv-ref/u32 buf-currentcnt 0)))
(write (list 'EVENT: r written current)) (newline)
(loop))))))
(exit 0)
... う〜ん。。
- たぶんFFIのlookupはSchemeシンボルじゃなくて文字列の方が良いんじゃないかという気はする。。内部的には文字列のハッシュテーブルで持って、lookupのAPIで適宜変換するのが良いかな。
-
address
は微妙なのでやっぱりpointer
に戻したい -
bytevector
のアドレスを取得できることを前提にするのはやっぱりよくないので、やっぱり抽象化した pointer オブジェクトを用意することにしたい
bytevectorのアドレスを 取得できない 処理系というのが存在する可能性がある。要はGCでオブジェクトを移動する可能性がある処理系が該当する。