Next: , Up: A More Detailed Example   [Contents][Index]


2.1 Creating a Wrapset

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>

Next: , Up: A More Detailed Example   [Contents][Index]