[gambit-list] is this a bug in ffi?
Álvaro Castro-Castilla
alvaro.castro.castilla at gmail.com
Mon Feb 6 17:37:34 EST 2012
Great! It works.
I've made this little variation to allow different scheme-type and c-type
names:
(define-macro
(import-enum-constants scheme-type c-type . names)
(define (interval lo hi)
(if (< lo hi) (cons lo (interval (+ lo 1) hi)) '()))
(let ((c-type-str (symbol->string c-type))
(nb-names (length names))
(wrapper (gensym)))
`(begin
(define ,wrapper
(c-lambda (int)
,scheme-type
,(string-append
"static " c-type-str " _tmp_[] = {\n"
(apply string-append
(map (lambda (i name)
(let ((name-str (symbol->string name)))
(string-append
(if (> i 0) "," "")
name-str)))
(interval 0 nb-names)
names))
"};\n"
"___ASSIGN_NEW_WITH_INIT(___result_voidstar,"
c-type-str ",_tmp_[___arg1]);\n")))
,@(map (lambda (i name)
`(define ,name (,wrapper ,i)))
(interval 0 nb-names)
names))))
On Mon, Feb 6, 2012 at 9:30 PM, Marc Feeley <feeley at iro.umontreal.ca> wrote:
>
> On 2012-02-06, at 1:04 PM, REPLeffect wrote:
>
> > 2012/2/6 Marc Feeley <feeley at iro.umontreal.ca>:
> >>
> >> On 2012-02-06, at 9:59 AM, Álvaro Castro-Castilla wrote:
> >>
> >>> Thank you Marc. Those are all better solutions than my wrapper
> function.
> >>>
> >>> Best regards
> >>>
> >>> Álvaro
> >>
> >> Actually, using a wrapper function is a good idea to reduce code size.
> Its intricacies can be hidden in a macro which generates the appropriate
> Scheme and C code. I've written something like this in the past and even
> posted an example to the Gambit mailing list (unfortunately my mail
> system's search function is broken right now so I can't find the message).
> >>
> >> Marc
> >>
> >
> > Marc,
> >
> > Is this the message you're referring to?
> >
> >
> https://mercure.iro.umontreal.ca/pipermail/gambit-list/2011-November/005445.html
>
> Yes. Using that macro as an inspiration, I wrote the following
> import-enum-constants macro which imports a number of enum constants
> without using a wrapper function:
>
> (c-declare #<<end-of-c-declare
>
> #include <stdio.h>
>
> typedef enum { A0, B0, C0, D0, E0, F0, G0, H0, I0, J0,
> A1, B1, C1, D1, E1, F1, G1, H1, I1, J1,
> A2, B2, C2, D2, E2, F2, G2, H2, I2, J2,
> A3, B3, C3, D3, E3, F3, G3, H3, I3, J3,
> A4, B4, C4, D4, E4, F4, G4, H4, I4, J4,
> A5, B5, C5, D5, E5, F5, G5, H5, I5, J5,
> A6, B6, C6, D6, E6, F6, G6, H6, I6, J6,
> A7, B7, C7, D7, E7, F7, G7, H7, I7, J7,
> A8, B8, C8, D8, E8, F8, G8, H8, I8, J8,
> A9, B9, C9, D9, E9, F9, G9, H9, I9, J9 } foo;
>
> void f(foo x) { printf("%d\n", x); }
>
> end-of-c-declare
> )
>
>
> ;;;---------------------------------------------------------------------------
>
> (define-macro (import-enum-constants type . names)
> (let ((type-str (symbol->string type)))
> `(begin
> ,@(map (lambda (name)
> (let ((name-str (symbol->string name)))
> `(define ,name
> ((c-lambda ()
> ,type
> ,(string-append
>
> "___ASSIGN_NEW_WITH_INIT(___result_voidstar,"
> type-str
> ","
> name-str
> ");"))))))
> names))))
>
>
> ;;;---------------------------------------------------------------------------
>
> (c-define-type foo "foo")
>
> (import-enum-constants foo
> A0 B0 C0 D0 E0 F0 G0 H0 I0 J0
> A1 B1 C1 D1 E1 F1 G1 H1 I1 J1
> A2 B2 C2 D2 E2 F2 G2 H2 I2 J2
> A3 B3 C3 D3 E3 F3 G3 H3 I3 J3
> A4 B4 C4 D4 E4 F4 G4 H4 I4 J4
> A5 B5 C5 D5 E5 F5 G5 H5 I5 J5
> A6 B6 C6 D6 E6 F6 G6 H6 I6 J6
> A7 B7 C7 D7 E7 F7 G7 H7 I7 J7
> A8 B8 C8 D8 E8 F8 G8 H8 I8 J8
> A9 B9 C9 D9 E9 F9 G9 H9 I9 J9
> )
>
> (define f (c-lambda (foo) void "f"))
>
> (f A0)
> (f F6)
> (f J9)
>
>
> When a wrapper function is used, the macro can be implemented like this:
>
>
> ;;;---------------------------------------------------------------------------
>
> (define-macro (import-enum-constants type . names)
>
> (define (interval lo hi)
> (if (< lo hi) (cons lo (interval (+ lo 1) hi)) '()))
>
> (let ((type-str (symbol->string type))
> (nb-names (length names))
> (wrapper (gensym)))
> `(begin
> (define ,wrapper
> (c-lambda (int)
> ,type
> ,(string-append
> "static " type-str " _tmp_[] = {\n"
> (apply string-append
> (map (lambda (i name)
> (let ((name-str (symbol->string name)))
> (string-append
> (if (> i 0) "," "")
> name-str)))
> (interval 0 nb-names)
> names))
> "};\n"
> "___ASSIGN_NEW_WITH_INIT(___result_voidstar," type-str
> ",_tmp_[___arg1]);\n")))
> ,@(map (lambda (i name)
> `(define ,name (,wrapper ,i)))
> (interval 0 nb-names)
> names))))
>
>
> ;;;---------------------------------------------------------------------------
>
> The version with the wrapper function is much more compact. On Mac OS X
> with LLVM gcc the first version compiles to a 80kb file (roughly 700 bytes
> of machine code per enum constant that is imported), and the version with a
> wrapper function compiles to a 20kb file (roughly a factor of 5 times more
> compact).
>
> Marc
>
> _______________________________________________
> Gambit-list mailing list
> Gambit-list at iro.umontreal.ca
> https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20120206/6e7077ab/attachment.htm>
More information about the Gambit-list
mailing list