[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
6.20.5.3 Void Pointers and Byte Access
Wrapped pointers are untyped, so they are essentially equivalent to C
void
pointers. As in C, the memory region pointed to by a
pointer can be accessed at the byte level. This is achieved using
bytevectors (see section Bytevectors). The (rnrs bytevector)
module contains procedures that can be used to convert byte sequences to
Scheme objects such as strings, floating point numbers, or integers.
- Scheme Procedure: pointer->bytevector pointer len [offset [uvec_type]]
- C Function: scm_pointer_to_bytevector (pointer, len, offset, uvec_type)
Return a bytevector aliasing the len bytes pointed to by pointer.
The user may specify an alternate default interpretation for the memory by passing the uvec_type argument, to indicate that the memory is an array of elements of that type. uvec_type should be something that
uniform-vector-element-type
would return, likef32
ors16
.When offset is passed, it specifies the offset in bytes relative to pointer of the memory region aliased by the returned bytevector.
Mutating the returned bytevector mutates the memory pointed to by pointer, so buckle your seatbelts.
- Scheme Procedure: bytevector->pointer bv [offset]
- C Function: scm_bytevector_to_pointer (bv, offset)
Return a pointer pointer aliasing the memory pointed to by bv or offset bytes after bv when offset is passed.
In addition to these primitives, convenience procedures are available:
- Scheme Procedure: dereference-pointer pointer
Assuming pointer points to a memory region that holds a pointer, return this pointer.
- Scheme Procedure: string->pointer string [encoding]
Return a foreign pointer to a nul-terminated copy of string in the given encoding, defaulting to the current locale encoding. The C string is freed when the returned foreign pointer becomes unreachable.
This is the Scheme equivalent of
scm_to_stringn
.
- Scheme Procedure: pointer->string pointer [length] [encoding]
Return the string representing the C string pointed to by pointer. If length is omitted or
-1
, the string is assumed to be nul-terminated. Otherwise length is the number of bytes in memory pointed to by pointer. The C string is assumed to be in the given encoding, defaulting to the current locale encoding.This is the Scheme equivalent of
scm_from_stringn
.
Most object-oriented C libraries use pointers to specific data
structures to identify objects. It is useful in such cases to reify the
different pointer types as disjoint Scheme types. The
define-wrapped-pointer-type
macro simplifies this.
- Scheme Syntax: define-wrapped-pointer-type type-name pred wrap unwrap print
Define helper procedures to wrap pointer objects into Scheme objects with a disjoint type. Specifically, this macro defines:
- pred, a predicate for the new Scheme type;
- wrap, a procedure that takes a pointer object and returns an object that satisfies pred;
- unwrap, which does the reverse.
wrap preserves pointer identity, for two pointer objects p1 and p2 that are
equal?
,(eq? (wrap p1) (wrap p2)) ⇒ #t
.Finally, print should name a user-defined procedure to print such objects. The procedure is passed the wrapped object and a port to write to.
For example, assume we are wrapping a C library that defines a type,
bottle_t
, and functions that can be passedbottle_t *
pointers to manipulate them. We could write:(define-wrapped-pointer-type bottle bottle? wrap-bottle unwrap-bottle (lambda (b p) (format p "#<bottle of ~a ~x>" (bottle-contents b) (pointer-address (unwrap-bottle b))))) (define grab-bottle ;; Wrapper for `bottle_t *grab (void)'. (let ((grab (pointer->procedure '* (dynamic-func "grab_bottle" libbottle) '()))) (lambda () "Return a new bottle." (wrap-bottle (grab))))) (define bottle-contents ;; Wrapper for `const char *bottle_contents (bottle_t *)'. (let ((contents (pointer->procedure '* (dynamic-func "bottle_contents" libbottle) '(*)))) (lambda (b) "Return the contents of B." (pointer->string (contents (unwrap-bottle b)))))) (write (grab-bottle)) ⇒ #<bottle of Château Haut-Brion 803d36>
In this example,
grab-bottle
is guaranteed to return a genuinebottle
object satisfyingbottle?
. Likewise,bottle-contents
errors out when its argument is not a genuinebottle
object.
Going back to the scm_numptob
example above, here is how we can
read its value as a C long
integer:
(use-modules (rnrs bytevectors)) (bytevector-uint-ref (pointer->bytevector numptob (sizeof long)) 0 (native-endianness) (sizeof long)) ⇒ 8
If we wanted to corrupt Guile’s internal state, we could set
scm_numptob
to another value; but we shouldn’t, because that
variable is not meant to be set. Indeed this point applies more widely:
the C API is a dangerous place to be. Not only might setting a value
crash your program, simply accessing the data pointed to by a dangling
pointer or similar can prove equally disastrous.
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on April 20, 2013 using texi2html 5.0.