Use another language to call a function: Difference between revisions

m
→‎Using carray: Nuke trailing spaces.
(→‎{{header|TXR}}: Remove first solution, improve carray solution, put callback discussion at end.)
m (→‎Using carray: Nuke trailing spaces.)
Line 1,103:
Callbacks are modeled as "FFI closures". The macro <code>deffi-cb</code> defines a function which itself isn't a callback, but is rather a combinator which converts a Lisp function into a FFI callback.
 
<lang txrlisp>(with-dyn-lib "./query.so"
(deffi query "query" void (closure)))
 
(deffi-cb query-cb int ((carray char) (ptr (array 1 size-t))))
 
(query (query-cb (lambda (buf sizeptr)
(symacrolet ((size [sizeptr 0]))
(let* ((s "Here am I")
(l (length s)))
(cond
((> l size) 0)
(t (carray-set-length buf size)
(carray-put buf s)
(set size l))))))))</lang>
 
Line 1,123:
 
Note that the obvious way of passing a <code>size_t</code> value by pointer, namely <code>(ptr size-t)</code> doesn't work. While the callback will receive the size (FFI will decode the pointer type's semantics and get the size value), updating the size will not propagate back to the caller, because it becomes, effectively, a by-value parameter. A <code>(ptr size-t)</code> object has to be embedded in an aggregate that is passed by reference, in order to have two-way semantics. Here we use the trick of treating the <code>size_t *</code> as an array of 1, which it ''de facto'' is. In the callback, we establish local symbol macro which lets us just refer to <code>[sizeptr 0]</code> it as <code>size</code>.
 
 
=== Using <code>cptr</code> and <code>memcpy</code> ===
543

edits