須藤です。 uim/iconv.cを見ていて気付いたのですが、SigSchemeはCのオブジェ クト(ポインタ)をラップしたSchemeオブジェクトがGCでfreeされ るときに、ついでにラップしたCのオブジェクトもfreeするフック のようなものを指定できないように見えます。
そのため、(iconv-release iconv)というように明示的にCのオブジェ クトをfreeしなければならなく、せっかくGCがあるのに少し寂しい 気がします。 ということで、CのオブジェクトをラップするSchemeオブジェクト を作るときに、Cのオブジェクトをfreeする関数を登録できるよう にするというのはどうでしょうか? とりえあず、簡単に実験してみました。 (SigSchemeのことはよくわかっていないので、storage-fattyの方 だけです。) まず、SigSchemeの方ですが、CのオブジェクトをラップするScheme オブジェクトにScmFreeFuncを登録できるようにして、free_cell() のときに登録されたScmFreeFunc呼び出します。 そして、uimの方で追加したSigScheme側の関数のバインディングを 作ってやると、このように書けるようになり、明示的に (iconv-release iconv) とfreeしなくてもGCのときに勝手に頑張ってくれるようになります。 Index: uim/iconv.c =================================================================== --- uim/iconv.c (revision 5679) +++ uim/iconv.c (working copy) @@ -377,7 +377,7 @@ if (!ic) return uim_scm_f(); - return MAKE_PTR(ic); + return MAKE_PTR_WITH_FREE_FUNC(ic, uim_iconv_release); } static uim_lisp @@ -396,17 +396,9 @@ return outbuf_; } -static uim_lisp -uim_ext_iconv_release(uim_lisp ic_) -{ - uim_iconv_release(C_PTR(ic_)); - return uim_scm_t(); -} - void uim_init_iconv_subrs(void) { uim_scm_init_proc2("iconv-open", uim_ext_iconv_open); uim_scm_init_proc2("iconv-code-conv", uim_ext_iconv_code_conv); - uim_scm_init_proc1("iconv-release", uim_ext_iconv_release); } --~--~---------~--~----~------------~-------~--~----~ Google Groups "uim-ja" group uim-ja@googlegroups.com http://groups.google.com/group/uim-ja/about -~----------~----~----~----~------~----~------~--~---
Index: sigscheme/src/storage-fatty.h =================================================================== --- sigscheme/src/storage-fatty.h (revision 5678) +++ sigscheme/src/storage-fatty.h (working copy) @@ -155,6 +155,7 @@ struct { void *value; + ScmFreeFunc free_func; } c_pointer; struct { @@ -431,11 +432,18 @@ #define SCM_SAL_C_POINTERP(o) (SCM_TYPE(o) == ScmCPointer) #define SCM_SAL_C_POINTER_VALUE(o) \ (SCM_AS_C_POINTER(o)->obj.c_pointer.value) +#define SCM_SAL_C_POINTER_FREE_FUNC(o) \ + (SCM_AS_C_POINTER(o)->obj.c_pointer.free_func) #define SCM_SAL_C_POINTER_SET_VALUE(o, ptr) \ (SCM_C_POINTER_VALUE(o) = (ptr)) -#define SCM_ISAL_C_POINTER_INIT(o, ptr) \ - (SCM_ENTYPE((o), ScmCPointer), \ - SCM_C_POINTER_SET_VALUE((o), (ptr))) +#define SCM_SAL_C_POINTER_SET_FREE_FUNC(o, free_func) \ + (SCM_SAL_C_POINTER_FREE_FUNC(o) = (free_func)) +#define SCM_ISAL_C_POINTER_INIT(o, ptr) \ + SCM_ISAL_C_POINTER_INIT_WITH_FREE_FUNC(o, ptr, NULL) +#define SCM_ISAL_C_POINTER_INIT_WITH_FREE_FUNC(o, ptr, free_func) \ + (SCM_ENTYPE((o), ScmCPointer), \ + SCM_C_POINTER_SET_VALUE((o), (ptr)), \ + SCM_SAL_C_POINTER_SET_FREE_FUNC((o), (free_func))) #define SCM_SAL_C_FUNCPOINTERP(o) (SCM_TYPE(o) == ScmCFuncPointer) #define SCM_SAL_C_FUNCPOINTER_VALUE(o) \ (SCM_AS_C_FUNCPOINTER(o)->obj.c_func_pointer.value) Index: sigscheme/src/storage.c =================================================================== --- sigscheme/src/storage.c (revision 5678) +++ sigscheme/src/storage.c (working copy) @@ -161,6 +161,11 @@ SCM_TYPESAFE_MACRO_VOID(SCM_ISAL_C_POINTER_INIT, \ (ScmObj, void *), \ ((obj), (ptr))) +/* SCM_C_POINTER_INIT_WITH_FREE_FUNC(obj, void *ptr, ScmFreeFunc free_func) */ +#define SCM_C_POINTER_INIT_WITH_FREE_FUNC(obj, ptr, free_func) \ + SCM_TYPESAFE_MACRO_VOID(SCM_ISAL_C_POINTER_INIT_WITH_FREE_FUNC, \ + (ScmObj, void *, ScmFreeFunc free_func), \ + ((obj), (ptr), (free_func))) /* SCM_C_FUNCPOINTER_INIT(obj, ScmCFunc ptr) */ #define SCM_C_FUNCPOINTER_INIT(obj, ptr) \ SCM_TYPESAFE_MACRO_VOID(SCM_ISAL_C_FUNCPOINTER_INIT, \ @@ -537,10 +542,16 @@ SCM_EXPORT ScmObj scm_make_cpointer(void *ptr) { + return scm_make_cpointer_with_free_func(ptr, NULL); +} + +SCM_EXPORT ScmObj +scm_make_cpointer_with_free_func(void *ptr, ScmFreeFunc free_func) +{ ScmObj obj; obj = scm_alloc_cell(); - SCM_C_POINTER_INIT(obj, ptr); + SCM_C_POINTER_INIT_WITH_FREE_FUNC(obj, ptr, free_func); return obj; } Index: sigscheme/src/storage-gc.c =================================================================== --- sigscheme/src/storage-gc.c (revision 5678) +++ sigscheme/src/storage-gc.c (working copy) @@ -870,9 +870,21 @@ case ScmFarsymbol: case ScmSubpat: case ScmCFuncPointer: - case ScmCPointer: case ScmValuePacket: break; + case ScmCPointer: +#if SCM_USE_SSCM_EXTENSIONS + { + void *value; + ScmFreeFunc free_func; + + value = SCM_SAL_C_POINTER_VALUE(cell); + free_func = SCM_SAL_C_POINTER_FREE_FUNC(cell); + if (value && free_func) + free_func(value); + } +#endif + break; #if SCM_DEBUG case ScmRational: case ScmReal: Index: sigscheme/src/storage-common.h =================================================================== --- sigscheme/src/storage-common.h (revision 5678) +++ sigscheme/src/storage-common.h (working copy) @@ -133,6 +133,7 @@ #if SCM_USE_SSCM_EXTENSIONS #define SCM_SAL_MAKE_C_POINTER scm_make_cpointer +#define SCM_SAL_MAKE_C_POINTER_WITH_FREE_FUNC scm_make_cpointer_with_free_func #define SCM_SAL_MAKE_C_FUNCPOINTER scm_make_cfunc_pointer #endif @@ -188,6 +189,7 @@ #endif #if SCM_USE_SSCM_EXTENSIONS SCM_EXPORT ScmObj scm_make_cpointer(void *ptr); +SCM_EXPORT ScmObj scm_make_cpointer_with_free_func(void *ptr, ScmFreeFunc free_func); SCM_EXPORT ScmObj scm_make_cfunc_pointer(ScmCFunc ptr); #endif #if SCM_USE_HYGIENIC_MACRO Index: sigscheme/src/sigscheme.h =================================================================== --- sigscheme/src/sigscheme.h (revision 5678) +++ sigscheme/src/sigscheme.h (working copy) @@ -448,8 +448,8 @@ typedef void (*ScmCFunc)(void); typedef void *(*ScmGCGateFunc)(void *); +typedef void (*ScmFreeFunc)(void *); - #if SCM_USE_HYGIENIC_MACRO /* Environment for looking up a free variable inserted by a hygienic * macro's template. References in syntax-rules are only looked up in @@ -729,6 +729,12 @@ (void *), \ (ptr)) +#define SCM_MAKE_C_POINTER_WITH_FREE_FUNC(ptr, free_func) \ + SCM_TYPESAFE_MACRO(SCM_SAL_MAKE_C_POINTER_WITH_FREE_FUNC, \ + ScmObj, \ + (void *, ScmFreeFunc), \ + (ptr, free_func)) + #define SCM_MAKE_C_FUNCPOINTER(ptr) \ SCM_TYPESAFE_MACRO(SCM_SAL_MAKE_C_FUNCPOINTER, \ ScmObj, \
Index: test/test-iconv.scm =================================================================== --- test/test-iconv.scm (revision 5681) +++ test/test-iconv.scm (working copy) @@ -36,20 +36,16 @@ (select-module test.iconv) (define (setup) - (uim-test-setup) - (uim-eval '(define iconv #f))) + (uim-test-setup)) (define (teardown) - (uim-eval '(if iconv - (iconv-release iconv))) (uim-test-teardown)) (define (test-conv) (assert-equal "あいうえお" (uim-read-from-string (ces-convert - (uim-eval '(begin - (set! iconv (iconv-open "eucJP" "utf-8")) + (uim-eval '(let ((iconv (iconv-open "eucJP" "utf-8"))) (iconv-code-conv iconv "あいうえお"))) "eucJP" "utf-8"))) #f) Index: uim/iconv.c =================================================================== --- uim/iconv.c (revision 5679) +++ uim/iconv.c (working copy) @@ -377,7 +377,7 @@ if (!ic) return uim_scm_f(); - return MAKE_PTR(ic); + return MAKE_PTR_WITH_FREE_FUNC(ic, uim_iconv_release); } static uim_lisp @@ -396,17 +396,9 @@ return outbuf_; } -static uim_lisp -uim_ext_iconv_release(uim_lisp ic_) -{ - uim_iconv_release(C_PTR(ic_)); - return uim_scm_t(); -} - void uim_init_iconv_subrs(void) { uim_scm_init_proc2("iconv-open", uim_ext_iconv_open); uim_scm_init_proc2("iconv-code-conv", uim_ext_iconv_code_conv); - uim_scm_init_proc1("iconv-release", uim_ext_iconv_release); } Index: uim/uim-scm-sigscheme.c =================================================================== --- uim/uim-scm-sigscheme.c (revision 5678) +++ uim/uim-scm-sigscheme.c (working copy) @@ -93,6 +93,11 @@ static void *uim_scm_make_str_directly_internal(char *str); static void *uim_scm_make_symbol_internal(const char *name); static void *uim_scm_make_ptr_internal(void *ptr); +struct make_ptr_with_free_func_args { + void *ptr; + uim_free_func_ptr free_func; +}; +static void *uim_scm_make_ptr_with_free_func_internal(struct make_ptr_with_free_func_args *args); static void *uim_scm_make_func_ptr_internal(uim_func_ptr func_ptr); static void *uim_scm_symbol_value_internal(const char *symbol_str); static void *uim_scm_symbol_value_int_internal(const char *symbol_str); @@ -406,6 +411,25 @@ return (void *)SCM_MAKE_C_POINTER(ptr); } +uim_lisp +uim_scm_make_ptr_with_free_func(void *ptr, uim_free_func_ptr free_func) +{ + struct make_ptr_with_free_func_args args; + + assert(uim_scm_gc_any_contextp()); + + args.ptr = ptr; + args.free_func = free_func; + return (uim_lisp)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)uim_scm_make_ptr_with_free_func_internal, + &args); +} + +static void * +uim_scm_make_ptr_with_free_func_internal(struct make_ptr_with_free_func_args *args) +{ + return (void *)SCM_MAKE_C_POINTER_WITH_FREE_FUNC(args->ptr, args->free_func); +} + uim_func_ptr uim_scm_c_func_ptr(uim_lisp func_ptr) { Index: uim/uim-scm-abbrev.h =================================================================== --- uim/uim-scm-abbrev.h (revision 5678) +++ uim/uim-scm-abbrev.h (working copy) @@ -62,6 +62,7 @@ #define MAKE_STR_DIRECTLY uim_scm_make_str_directly #define MAKE_SYM uim_scm_make_symbol #define MAKE_PTR uim_scm_make_ptr +#define MAKE_PTR_WITH_FREE_FUNC uim_scm_make_ptr_with_free_func #define MAKE_FPTR uim_scm_make_func_ptr #define INTP uim_scm_intp Index: uim/uim-scm.h =================================================================== --- uim/uim-scm.h (revision 5678) +++ uim/uim-scm.h (working copy) @@ -89,6 +89,7 @@ typedef struct uim_opaque * uim_lisp; typedef void (*uim_func_ptr)(void); typedef void *(*uim_gc_gate_func_ptr)(void *); +typedef void (*uim_free_func_ptr)(void *object); /* subsystem interfaces */ @@ -161,6 +162,7 @@ void *uim_scm_c_ptr(uim_lisp ptr); void uim_scm_nullify_c_ptr(uim_lisp ptr); uim_lisp uim_scm_make_ptr(void *ptr); +uim_lisp uim_scm_make_ptr_with_free_func(void *ptr, uim_free_func_ptr free_func); uim_func_ptr uim_scm_c_func_ptr(uim_lisp func_ptr); uim_lisp uim_scm_make_func_ptr(uim_func_ptr func_ptr);