-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathffi.rkt
204 lines (169 loc) · 7.13 KB
/
ffi.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#lang racket/base
(provide (all-defined-out))
(provide (all-from-out ffi/unsafe))
(provide (all-from-out ffi/unsafe/define))
(provide (all-from-out ffi/unsafe/alloc))
(provide (all-from-out '#%foreign))
(provide (rename-out [ctype-c->scheme ctype-c->racket]
[ctype-scheme->c ctype-racket->c]))
(require ffi/unsafe)
(require ffi/unsafe/define)
(require ffi/unsafe/alloc)
(require racket/unsafe/ops)
(require (only-in '#%foreign
ctype-basetype
ctype-c->scheme
ctype-scheme->c))
(require "digitama/ffi.rkt")
(require "digitama/path.rkt")
(require (for-syntax racket/base))
(require (for-syntax syntax/parse))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-syntax (digimon-ffi-lib stx)
(syntax-parse stx #:literals []
[(_ libname
(~alt (~optional (~seq #:global? global?:expr) #:defaults ([global? #'#true]))
(~optional (~seq #:on-fail on-fail:expr) #:defaults ([on-fail #'#false]))
(~optional (~seq #:subdir subdir:expr) #:defaults ([subdir #'#false]))
(~optional (~seq #:custodian cust:expr) #:defaults ([cust #'#false])))
...)
(syntax/loc stx
(let ([modpath (variable-reference->module-source (#%variable-reference))]
[libpath (system-library-subpath #false)])
(if (not (path? modpath)) ; when distributed as a standalone executable
(ffi-lib (build-path (ffi-distributed-library-path) libpath libname)
#:global? global?
#:custodian cust
#:fail (λ [] (ffi-lib #:global? global? #:fail on-fail #:custodian cust
(build-path libpath libname))))
(ffi-lib libname
#:fail on-fail
#:global? global?
#:custodian cust
#:get-lib-dirs
(λ [] (list (native-rootdir/compiled modpath subdir)
(native-rootdir modpath subdir)))))))]))
(define-syntax (define-ffi-parameter stx)
(syntax-parse stx #:literals []
[(_ sym:id (~optional #:in) lib (~optional #:as) type)
(syntax/loc stx
(define sym (make-c-parameter 'sym lib type)))]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define _char (make-ctype _byte char->integer integer->char))
(define _uchar (make-ctype _ubyte char->integer integer->char))
(define _any_string (make-ctype _string (λ [v] (if (string? v) v (format "~a" v))) values))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define _take_memory_snapshot_t (_fun _string -> _void))
(define _register_variable_t (_fun _string _symbol _uintptr _symbol -> _void))
(define _register_array_t (_fun _string _symbol _uintptr _symbol _size -> _void))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define &
(lambda [ptr]
(cast ptr _pointer _uintptr)))
(define %p
(case-lambda
[(ptr) (let ([addr (cond [(cpointer? ptr) (& ptr)]
[(exact-integer? ptr) ptr]
[else (& (ffi-obj-ref ptr #false))])])
(string-append "0x" (number->string addr 16)))]
[(sym dylib) (%p (ffi-obj-ref sym dylib))]))
(define memory-step
(lambda [ptr type [maybe-memory #false]]
(define memory
(cond [(bytes? maybe-memory) memory]
[(byte? maybe-memory) (make-bytes maybe-memory)]
[else (make-bytes (ctype-sizeof type))]))
(memmove memory 0 ptr 0 1 type)
(values memory
(ptr-ref ptr type)
(ptr-add ptr 1 type))))
(define memory-step!
(lambda [ptr type [maybe-memory #false]]
(define memory
(cond [(bytes? maybe-memory) memory]
[(byte? maybe-memory) (make-bytes maybe-memory)]
[else (make-bytes (ctype-sizeof type))]))
(memmove memory 0 ptr 0 1 type)
(values memory
(ptr-ref ptr type)
(ptr-add! ptr 1 type))))
(define memory-step*
(lambda [ptr type memory &datum]
(define count
(if (vector? &datum)
(let ([size (unsafe-vector-length &datum)])
(for ([idx (in-range size)])
(unsafe-vector-set! &datum idx (ptr-ref ptr type idx)))
size)
(begin (unsafe-set-box! &datum (ptr-ref ptr type)) 1)))
(memmove memory 0 ptr 0 count type)
(ptr-add ptr count type)))
(define memory-step*!
(lambda [ptr type memory &datum]
(define count
(if (vector? &datum)
(let ([size (unsafe-vector-length &datum)])
(for ([idx (in-range size)])
(unsafe-vector-set! &datum idx (ptr-ref ptr type idx)))
size)
(begin (unsafe-set-box! &datum (ptr-ref ptr type)) 1)))
(memmove memory 0 ptr 0 count type)
(ptr-add! ptr count type)))
(define memory-step-for-bytes
(lambda [ptr type [count 1]]
(define size (ctype-sizeof type))
(define memory (make-bytes (* size count)))
(memmove memory 0 ptr 0 count type)
(values memory (ptr-add ptr count type))))
(define memory-step-for-bytes!
(lambda [ptr type [count 1]]
(define size (ctype-sizeof type))
(define memory (make-bytes (* size count)))
(memmove memory 0 ptr 0 count type)
(values memory (ptr-add! ptr count type))))
(define memory-step-for-datum
(lambda [ptr type]
(values (ptr-ref ptr type)
(ptr-add ptr 1 type))))
(define memory-step-for-datum!
(lambda [ptr type]
(values (ptr-ref ptr type)
(ptr-add! ptr 1 type))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define cpointer*?
(lambda [v]
(and v (cpointer? v))))
(define make-ctype/release
(lambda [ctype deallocator]
(define basetype (ctype-basetype ctype))
(define racket->c (ctype-scheme->c ctype))
(define c->racket (ctype-c->scheme ctype))
(define (wrap datum)
((deallocator (λ [] datum))))
(make-ctype (or basetype ctype) racket->c
(λ [c] (wrap (if c->racket (c->racket c) c))))))
(define make-ctype*
(lambda [ctype out-hook [in-hook #false]]
(define basetype (ctype-basetype ctype))
(define racket->c (ctype-scheme->c ctype))
(define c->racket (ctype-c->scheme ctype))
(define (ctype-in-hook rkt)
(define v (in-hook rkt))
(if (void? v) rkt v))
(define (ctype-out-hook rkt)
(define v (out-hook rkt))
(if (void? v) rkt v))
(make-ctype (or basetype ctype)
(cond [(not in-hook) racket->c]
[(not racket->c) in-hook]
[else (λ [rkt] (ctype-in-hook rkt))])
(cond [(not out-hook) c->racket]
[(not c->racket) ctype-out-hook]
[else (λ [c] (ctype-out-hook (c->racket c)))]))))
(define ctype-bind-box
(lambda [ctype &dest]
(unless (box? &dest)
(raise-argument-error
'ctype-bind-box "box?" &dest))
(make-ctype* ctype
(λ [r] (unsafe-set-box! &dest r)))))