This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
I'd like to add some information in addition to what Maciej has said. Daniel R Risacher <risacher@worldnet.att.net> writes: [...] > Suppose your C library has data types Foo and Bar. > A Foo can contain a pointer to a Bar. You write the functions > Clib-make-new-foo, Clib-make-new-bar, and > Clib-foo-set-pointer-to-bar. [...] > What is the "right way" to solve this dilemma? Is there one? Yes, in my view there is a "right way". The problem you're describing, keeping track of references and allocated memory, is the natural task for the garbage collector. So, you have to tell the garbage collector that Foo points to Bar somehow. Luckily, this is possible and quite easy. The natural way to wrap C data types in Guile is by using smobs: *** Declaration of the C level structure containing a reference to bar struct foo { ... SCM bar; ... }; *** This is the type tag long foo_type; *** The constructor SCM_PROC (s_make_foo, "make-foo", 0, 0, 0, scm_make_foo); SCM scm_make_foo () { SCM z; char *foo = scm_must_malloc (sizeof (struct foo), s_make_foo); SCM_NEWCELL (z); SCM_DEFER_INTS; SCM_SETCDR (z, foo); SCM_SETCAR (z, foo_type); SCM_ALLOW_INTS; return z; } *** This function tells the garbage collector how to mark foo objects. *** This is where we make it aware of the reference to bar. static SCM markfoo (SCM obj) { SCM_SETGC8MARK (obj); /* Mark the smob itself. */ /* The garbage collector continues to mark whatever we return. */ return ((struct foo *) SCM_CDR (obj))->bar; } *** Tell Guile how to free foo objects. static scm_sizet freefoo (SCM obj) { scm_must_free ((char*) SCM_CDR (obj)); return sizeof (struct foo); } *** Tell Guile how to print foo objects. static int prinarb (exp, port, pstate) SCM exp; SCM port; scm_print_state *pstate; { scm_gen_puts (scm_regular_string, "#<foo>", port); return 1; } *** This struct defines the smob data type foo static scm_smobfuns foosmob = { markfoo, freefoo, prinfoo, 0 }; *** This is the init function of the file defining foo. *** Use `guile-snarf' to produce "foo.x". (See libguile Makefile.) void scm_init_foo () { foo_type = scm_newsmob (&foosmob); #include "foo.x" } Above, I have assumed that `bar' is also wrapped by a smob type, and that the foo struct points to this Scheme object. As Maciej said, things needs to be handled differently if we lack a pointer to the Scheme object, but this is a situation I'd try to avoid. Best regards, /mdj