FFI on cygwin

以前Cygwinのビルドを通したので、CygwinmoshではFFIが使える。以前のサンプルはそのまま実行できる。

;; generate png image with Cairo library.
(import (rnrs)
        (mosh ffi))

(let* ((libcairo (open-shared-library "libcairo-2.dll"))
         (cairo-image-surface-create (c-function libcairo void* cairo_image_surface_create int int int))
         (cairo-surface-write-to-png (c-function libcairo int cairo_surface_write_to_png void* char*))
         (cairo-create (c-function libcairo void* cairo_create void*))
         (set-line-width (c-function libcairo void cairo_set_line_width void* double))
         (rgba (c-function libcairo void cairo_set_source_rgba void* double double double double))
         (move-to (c-function libcairo void cairo_move_to void* double double))
         (line-to (c-function libcairo void cairo_line_to void* double double))
         (TOY-show-text (c-function libcairo void cairo_show_text void* char*))
         (stroke (c-function libcairo void cairo_stroke void*)))

       (let* ((surface (cairo-image-surface-create 1 300 300))
              (ctx (cairo-create surface)))
         (rgba ctx 1.0 1.0 1.0 1.0)
         (set-line-width ctx 8.0)
         (move-to ctx 10.0 10.0)
         (line-to ctx 10.0 290.0)
         (line-to ctx 290.0 290.0)
         (line-to ctx 290.0 10.0)
         (line-to ctx 10.0 10.0)
         (move-to ctx 100.0 150.0)
         (TOY-show-text ctx "mosh")
         (stroke ctx)
         (display (cairo-surface-write-to-png surface "test.png"))))

libcairo.soの代わりにlibcairo-2.dllをopenしていることに注意。この辺は、適当なwrapperライブラリを用意する必要があるだろう。
MinGWではまだ使えない。単にdlopenに相当する処理をLoadLibraryで行えば原理上は出来る。(今MinGW版は別の問題 = pre-compile cacheの置き場所の問題があるので保留中)
重要な問題は、CygwinMinGWも、BoehmGCが要求する"dlopenのフック"を実現できていない疑惑があることで、回収可能なオブジェクトのポインタがDLLのコンテキストに渡った時に問題が起こる可能性がある。もっとも、通常のシチュエーションではDLLに渡すデータを回収不能とマークするか(なぜならDLLはGCのインターフェースでメモリを確保してくれないので、どっちにせよ回収可能なメモリは作ることが出来ない)、渡す前にコピーしてしまうのが望ましい。