Next: Defining New Wrapped Types, Previous: A More Detailed Example, Up: Usage
Inside the wrapset specification file, the first thing you have to do is create the wrapset class (for a detailed explanation, refer to see Wrapsets). But before that, you have to tell Guile that you'll use the GOOPS and G-Wrap modules. So the most trivial wrapper module possible would look something like this:
(use-modules (oop goops) (g-wrap) (g-wrap guile))
(define-class <miscutils-wrapset> (<gw-guile-wrapset>)
#:id 'miscutils)
(define-method (initialize (ws <miscutils-wrapset>) initargs)
(next-method ws (append '(#:module (miscutils)) initargs)))
Note how the Guile module that the wrapset should reside in is passed
to the next-method of initialize as a keyword argument.
However, this wrapset won't let you do much. In particular, a newly
created wrapset doesn't know about any wrapped types. In general
you'll probably want to be able to use the standard set of G-Wrap
wrapped types which include support for int, double, strings, etc. If
so, then you need to add a #:dependencies keyword argument to
the class definition:
(define-class <miscutils-wrapset> (<gw-guile-wrapset>)
#:id 'miscutils
#:dependencies '(standard))
Now you can start wrapping functions using the default set of wrapped
types with calls to wrap-function!. To wrap
join_strings and seconds_since, you would
want to say something like this:
(define-method (initialize (ws <miscutils-wrapset>) initargs)
(next-method ws (append '(#:module (miscutils)) initargs))
(wrap-function!
ws
#:name 'join_strings
#:returns 'mchars
#:c-name "join_strings"
#:arguments '((mchars a) (mchars b))
#:description "Return a string consisting of a followed by b.")
(wrap-function!
ws
#:name 'seconds-since-dow
#:returns 'double
#:c-name "seconds_since_dow"
#:arguments '((uint day-of-week))
#:description "Given day-of-week (ranging 1-7), return elapsed time since then."))
wrap-function!'s arguments should be quite obvious. They are
detailed in See Wrapping a C Function.
Actually, the example given above won't work because specifying
mchars (roughly G-Wrap's type for char*, see C Types Provided in the Standard Wrapset) alone doesn't
provide enough information about the allocation semantics of the
argument or return value. G-Wrap needs to know whether a char*
argument that's passed in to a function should be considered to be
"owned" by the function after the C function returns, or should be
considered caller owned, and hence safe for deletion if appropriate.
So G-Wrap requires you to be explicit, and provides two type options
for string type arguments and return values: caller-owned and
callee-owned. The "m" in mchars stands for
malloc, since it's conceivable that for some C functions, the
argument or result might need to be allocated/freed via some other
mechanism.
So, for our example API, let's presume that join_strings takes
two strings that are owned by the caller and returns a newly allocated
string that will also be owned by the caller. Given that, the correct
way to wrap this function is:
(wrap-function!
ws
#:name 'join-strings
#:returns '(mchars caller-owned)
#:c-name "join_strings"
#:arguments '(((mchars caller-owned) a) ((mchars caller-owned) b))
#:description "Return a string consisting of a followed by b.")
At this point, we have a wrapset named "miscutils" that wraps our two C functions so that when the wrapper module's C code is generated, compiled, and then loaded back into Guile, we should be able to call these C functions normally. You could use it like this:
guile> (use-modules (miscutils))
guile> (join-strings "out" "let")
"outlet"
guile> (seconds-since-dow 1)
3099.232
guile>