Is there a way to register or implement a printer for a specific foreign type?
-Jason
Afficher les réponses par date
On 2013-03-17, at 7:25 PM, Jason Felice jason.m.felice@gmail.com wrote:
Is there a way to register or implement a printer for a specific foreign type?
-Jason
The Scheme printer (that is used for the implementation of write, display, pretty-print, and print) is bound to the global variable ##wr, which can be assigned. By redefining ##wr it is possible to intercept the printing of all objects, and to filter out the foreign objects.
Here's some sample code. This approach could be integrated with a macro to define C structs or classes so that a printer for that type is automatically created.
Marc
(include "~~lib/_gambit#.scm")
(define foreign-writers (make-table))
(define (write-foreign we obj) (case (macro-writeenv-style we) ((mark) (##wr-mark we obj)) (else (let ((tags (##foreign-tags obj))) (if (##pair? tags) ((table-ref foreign-writers (##car tags) ##wr-foreign) we obj) (##wr-foreign we obj))))))
(let ((old-wr ##wr)) (set! ##wr (lambda (we obj) (if (##foreign? obj) (write-foreign we obj) (old-wr we obj)))))
(c-declare #<<end-of-c-declare
#include <stdlib.h>
typedef struct { int x, y; } point;
point *make_point( int x, int y ) { point *p = ___CAST(point*, malloc(sizeof(point))); p->x = x; p->y = y; }
int point_x( point* p ) { return p->x; } int point_y( point* p ) { return p->y; }
end-of-c-declare )
(c-define-type point "point") (c-define-type point* (pointer point))
(define make-point (c-lambda (int int) point* "make_point")) (define point-x (c-lambda (point*) int "point_x")) (define point-y (c-lambda (point*) int "point_y"))
(define p (make-point 11 22))
(pp p) ;; prints: #<point* #2 0x1006064d0>
(table-set! foreign-writers 'point* (lambda (we obj) (##wr-str we "{") (##wr we (point-x obj)) (##wr-str we ",") (##wr we (point-y obj)) (##wr-str we "}")))
(pp p) ;; prints: {11,22}
Here's a module that delivers this.
Use:
(ffi-write-transformer-add! 'name-of-your-ffi-type (lambda (v) `(name-of-constructor-procedure-to-create-an-instance-of-this-ffi-type [ arguments needed to constructor to produce an instance exactly like the one in the v variable ])))
so you do sth like
(ffi-write-transformer-add! 'jasons-2d-coord (lambda (v) `(make-jason-2d-coord ,(jason-2d-coord-x v) ,(jason-2d-coord-y v)))
REPL interaction now looks like
(make-jason-2d-coord 10 20)
#.(make-jason-2d-coord 10 20)
(rather than #<foreign jason-2d-coord #x1234567>)
Brgds
2013/3/18 Marc Feeley feeley@iro.umontreal.ca
On 2013-03-17, at 7:25 PM, Jason Felice jason.m.felice@gmail.com wrote:
Is there a way to register or implement a printer for a specific foreign
type?
-Jason
The Scheme printer (that is used for the implementation of write, display, pretty-print, and print) is bound to the global variable ##wr, which can be assigned. By redefining ##wr it is possible to intercept the printing of all objects, and to filter out the foreign objects.
Here's some sample code. This approach could be integrated with a macro to define C structs or classes so that a printer for that type is automatically created.
Marc
(include "~~lib/_gambit#.scm")
(define foreign-writers (make-table))
(define (write-foreign we obj) (case (macro-writeenv-style we) ((mark) (##wr-mark we obj)) (else (let ((tags (##foreign-tags obj))) (if (##pair? tags) ((table-ref foreign-writers (##car tags) ##wr-foreign) we obj) (##wr-foreign we obj))))))
(let ((old-wr ##wr)) (set! ##wr (lambda (we obj) (if (##foreign? obj) (write-foreign we obj) (old-wr we obj)))))
(c-declare #<<end-of-c-declare
#include <stdlib.h>
typedef struct { int x, y; } point;
point *make_point( int x, int y ) { point *p = ___CAST(point*, malloc(sizeof(point))); p->x = x; p->y = y; }
int point_x( point* p ) { return p->x; } int point_y( point* p ) { return p->y; }
end-of-c-declare )
(c-define-type point "point") (c-define-type point* (pointer point))
(define make-point (c-lambda (int int) point* "make_point")) (define point-x (c-lambda (point*) int "point_x")) (define point-y (c-lambda (point*) int "point_y"))
(define p (make-point 11 22))
(pp p) ;; prints: #<point* #2 0x1006064d0>
(table-set! foreign-writers 'point* (lambda (we obj) (##wr-str we "{") (##wr we (point-x obj)) (##wr-str we ",") (##wr we (point-y obj)) (##wr-str we "}")))
(pp p) ;; prints: {11,22}
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Thanks Marc & Mikael!
I put a not to myself to put this into the first "release" of the objc bridge, which is coming along swimingly right now since I discovered that libffi on iOS issues were resolved (and not as bad as I had heard to begin with). Deleted a bunch of code, and now it's pretty simple.
-Jason
On Wed, Mar 20, 2013 at 4:09 PM, Mikael mikael.rcv@gmail.com wrote:
Here's a module that delivers this.
Use:
(ffi-write-transformer-add! 'name-of-your-ffi-type (lambda (v) `(name-of-constructor-procedure-to-create-an-instance-of-this-ffi-type [ arguments needed to constructor to produce an instance exactly like the one in the v variable ])))
so you do sth like
(ffi-write-transformer-add! 'jasons-2d-coord (lambda (v) `(make-jason-2d-coord ,(jason-2d-coord-x v) ,(jason-2d-coord-y v)))
REPL interaction now looks like
(make-jason-2d-coord 10 20)
#.(make-jason-2d-coord 10 20)
(rather than #<foreign jason-2d-coord #x1234567>)
Brgds
2013/3/18 Marc Feeley feeley@iro.umontreal.ca
On 2013-03-17, at 7:25 PM, Jason Felice jason.m.felice@gmail.com wrote:
Is there a way to register or implement a printer for a specific
foreign type?
-Jason
The Scheme printer (that is used for the implementation of write, display, pretty-print, and print) is bound to the global variable ##wr, which can be assigned. By redefining ##wr it is possible to intercept the printing of all objects, and to filter out the foreign objects.
Here's some sample code. This approach could be integrated with a macro to define C structs or classes so that a printer for that type is automatically created.
Marc
(include "~~lib/_gambit#.scm")
(define foreign-writers (make-table))
(define (write-foreign we obj) (case (macro-writeenv-style we) ((mark) (##wr-mark we obj)) (else (let ((tags (##foreign-tags obj))) (if (##pair? tags) ((table-ref foreign-writers (##car tags) ##wr-foreign) we obj) (##wr-foreign we obj))))))
(let ((old-wr ##wr)) (set! ##wr (lambda (we obj) (if (##foreign? obj) (write-foreign we obj) (old-wr we obj)))))
(c-declare #<<end-of-c-declare
#include <stdlib.h>
typedef struct { int x, y; } point;
point *make_point( int x, int y ) { point *p = ___CAST(point*, malloc(sizeof(point))); p->x = x; p->y = y; }
int point_x( point* p ) { return p->x; } int point_y( point* p ) { return p->y; }
end-of-c-declare )
(c-define-type point "point") (c-define-type point* (pointer point))
(define make-point (c-lambda (int int) point* "make_point")) (define point-x (c-lambda (point*) int "point_x")) (define point-y (c-lambda (point*) int "point_y"))
(define p (make-point 11 22))
(pp p) ;; prints: #<point* #2 0x1006064d0>
(table-set! foreign-writers 'point* (lambda (we obj) (##wr-str we "{") (##wr we (point-x obj)) (##wr-str we ",") (##wr we (point-y obj)) (##wr-str we "}")))
(pp p) ;; prints: {11,22}
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
On 2013-03-21, at 9:38 AM, Jason Felice jason.m.felice@gmail.com wrote:
Thanks Marc & Mikael!
I put a not to myself to put this into the first "release" of the objc bridge, which is coming along swimingly right now since I discovered that libffi on iOS issues were resolved (and not as bad as I had heard to begin with). Deleted a bunch of code, and now it's pretty simple.
Wonderful!
Marc
Whats macro-writeenv-style and ##wr-mark about?
On Thu, Mar 21, 2013 at 9:48 AM, Marc Feeley feeley@iro.umontreal.cawrote:
On 2013-03-21, at 9:38 AM, Jason Felice jason.m.felice@gmail.com wrote:
Thanks Marc & Mikael!
I put a not to myself to put this into the first "release" of the objc
bridge, which is coming along swimingly right now since I discovered that libffi on iOS issues were resolved (and not as bad as I had heard to begin with). Deleted a bunch of code, and now it's pretty simple.
Wonderful!
Marc
On 2013-03-24, at 1:16 PM, Jason Felice jason.m.felice@gmail.com wrote:
Whats macro-writeenv-style and ##wr-mark about?
The style field of a writeenv indicates the style in which the object is to be written. Currently the style can be
- write (11 "abc" 22) is written as: (11 "abc" 22) - display (11 "abc" 22) is written as: (11 abc 22) - print (11 "abc" 22) is written as: 11abc22 - pretty-print uses indentation/line breaks for pretty printing - mark used by #n=... notation
So the mark style is special in that it does not produce output. It is used when the readtable-sharing-allowed? flag is set:
(define (wr obj allow?)
(call-with-output-string '() (lambda (p) (output-port-readtable-set! p (readtable-sharing-allowed?-set (output-port-readtable p) allow?)) (write obj p))))
(wr (let ((x (cons 11 22))) (list x x)) #f)
"((11 . 22) (11 . 22))"
(wr (let ((x (cons 11 22))) (list x x)) #t)
"(#0=(11 . 22) #0#)"
The write/display/print/pretty-print procedures will make a first pass over the object/subobjects with style=mark. This is to gather in a table all the subobjects to write. Then, during the second pass, the #n=... notation will be used when an object has been marked more than once during the mark pass.
Marc