unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* FFI support for disjoint types
@ 2010-11-11 16:24 Ludovic Courtès
  2010-11-20 21:59 ` Andy Wingo
  2011-01-30 22:30 ` Ludovic Courtès
  0 siblings, 2 replies; 4+ messages in thread
From: Ludovic Courtès @ 2010-11-11 16:24 UTC (permalink / raw)
  To: guile-devel

Hello!

I’ve used the macro below in a couple of projects.  It allows the
creation of disjoint Scheme types for disjoint C pointer types, and
takes care of preserving eq?-ness for equal C pointers.

Example:

--8<---------------cut here---------------start------------->8---
;; Create a wrapped pointer type `class?'.
(define-wrapped-pointer-type class?
  wrap-class unwrap-class print-class)

(define lookup-class
  (let ((f (libchop-function '* "class_lookup" ('*))))
    (lambda (name)
      (let ((ptr (f (string->pointer name))))
        (if (null-pointer? ptr)
            #f

            ;; Wrap the object pointer so that it appears as an object
            ;; that matches `class?' at the Scheme level.
            (wrap-class ptr))))))

(define (class-name c)
  ;; C is a `class?' object, so unwrap it to get the underlying
  ;; pointer.
  (let ((ptr (make-pointer (+ (pointer-address (unwrap-class c))
                              %offset-of-name))))
    (pointer->string (dereference-pointer ptr))))
--8<---------------cut here---------------end--------------->8---

Code:

--8<---------------cut here---------------start------------->8---
(define-syntax define-wrapped-pointer-type
  (lambda (stx)
    (syntax-case stx ()
      ((_ pred wrap unwrap print) ;; hygiene
       (with-syntax ((type-name (datum->syntax #'pred (gensym)))
                     (%wrap     (datum->syntax #'wrap (gensym))))
         #'(begin
             (define-record-type type-name
               (%wrap pointer)
               pred
               (pointer unwrap))
             (define wrap
               ;; Use a weak hash table to preserve pointer identity, i.e.,
               ;; PTR1 == PTR2 <-> (eq? (wrap PTR1) (wrap PTR2)).
               (let ((ptr->obj (make-weak-value-hash-table)))
                 (lambda (ptr)
                   (or (hash-ref ptr->obj ptr)
                       (let ((o (%wrap ptr)))
                         (hash-set! ptr->obj ptr o)
                         o)))))
             (set-record-type-printer! type-name print))))
      ((_ type-name print) ;; lazyness
       (let* ((type-name*  (syntax->datum #'type-name))
              (pred-name   (datum->syntax #'type-name
                                          (symbol-append type-name* '?)))
              (wrap-name   (datum->syntax #'type-name
                                          (symbol-append 'wrap- type-name*)))
              (%wrap-name  (datum->syntax #'type-name
                                          (symbol-append '%wrap- type-name*)))
              (unwrap-name (datum->syntax #'type-name
                                          (symbol-append 'unwrap-
                                                         type-name*))))
         (with-syntax ((pred   pred-name)
                       (wrap   wrap-name)
                       (%wrap  %wrap-name)
                       (unwrap unwrap-name))
           #'(define-wrapped-pointer-type pred wrap unwrap print)))))))
--8<---------------cut here---------------end--------------->8---

The second pattern in the macro is convenient but unhygienic, so I’m
inclined to remove it.

Thoughts?

What about adding it to (system foreign), along with documentation?

Thanks,
Ludo’.





^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-01-30 22:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-11 16:24 FFI support for disjoint types Ludovic Courtès
2010-11-20 21:59 ` Andy Wingo
2010-11-21 22:36   ` Ludovic Courtès
2011-01-30 22:30 ` Ludovic Courtès

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).