FFI on cygwin
以前Cygwinのビルドを通したので、Cygwinのmoshでは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の置き場所の問題があるので保留中)
重要な問題は、CygwinもMinGWも、BoehmGCが要求する"dlopenのフック"を実現できていない疑惑があることで、回収可能なオブジェクトのポインタがDLLのコンテキストに渡った時に問題が起こる可能性がある。もっとも、通常のシチュエーションではDLLに渡すデータを回収不能とマークするか(なぜならDLLはGCのインターフェースでメモリを確保してくれないので、どっちにせよ回収可能なメモリは作ることが出来ない)、渡す前にコピーしてしまうのが望ましい。