alien: improve documentation

db4
Slava Pestov 2009-09-26 21:28:11 -05:00
parent 685c4143c9
commit 77fa16c76f
11 changed files with 166 additions and 78 deletions

View File

@ -1,12 +0,0 @@
USING: help.syntax help.markup byte-arrays alien.c-types alien.data ;
IN: alien.arrays
ARTICLE: "c-arrays" "C arrays"
"C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "."
$nl
"C type specifiers for array types are documented in " { $link "c-types-specs" } "."
$nl
"Specialized sequences are provided for accessing memory as an array of primitive type values. These sequences are implemented in the " { $vocab-link "specialized-arrays" } " vocabulary set. They can also be loaded and constructed through their primitive C types:"
{ $subsection require-c-array }
{ $subsection <c-array> }
{ $subsection <c-direct-array> } ;

View File

@ -10,7 +10,7 @@ HELP: byte-length
{ $contract "Outputs the size of the byte array, struct, or specialized array data in bytes." } ;
HELP: heap-size
{ $values { "type" string } { "size" math:integer } }
{ $values { "name" "a C type name" } { "size" math:integer } }
{ $description "Outputs the number of bytes needed for a heap-allocated value of this C type." }
{ $examples
{ $example "USING: alien alien.c-types prettyprint ;\nint heap-size ." "4" }
@ -18,16 +18,16 @@ HELP: heap-size
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
HELP: stack-size
{ $values { "type" string } { "size" math:integer } }
{ $values { "name" "a C type name" } { "size" math:integer } }
{ $description "Outputs the number of bytes to reserve on the C stack by a value of this C type. In most cases this is equal to " { $link heap-size } ", except on some platforms where C structs are passed by invisible reference, in which case a C struct type only uses as much space as a pointer on the C stack." }
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
HELP: <c-type>
{ $values { "type" hashtable } }
{ $values { "c-type" c-type } }
{ $description "Creates a prototypical C type. User code should use higher-level facilities to define C types; see " { $link "c-data" } "." } ;
HELP: no-c-type
{ $values { "type" string } }
{ $values { "name" "a C type name" } }
{ $description "Throws a " { $link no-c-type } " error." }
{ $error-description "Thrown by " { $link c-type } " if a given string does not name a C type. When thrown during compile time, indicates a typo in an " { $link alien-invoke } " or " { $link alien-callback } " form." } ;
@ -35,32 +35,32 @@ HELP: c-types
{ $var-description "Global variable holding a hashtable mapping C type names to C types. Use the " { $link c-type } " word to look up C types." } ;
HELP: c-type
{ $values { "name" string } { "type" hashtable } }
{ $values { "name" "a C type" } { "c-type" c-type } }
{ $description "Looks up a C type by name." }
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
HELP: c-getter
{ $values { "name" string } { "quot" { $quotation "( c-ptr n -- obj )" } } }
{ $values { "name" "a C type" } { "quot" { $quotation "( c-ptr n -- obj )" } } }
{ $description "Outputs a quotation which reads values of this C type from a C structure." }
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
HELP: c-setter
{ $values { "name" string } { "quot" { $quotation "( obj c-ptr n -- )" } } }
{ $values { "name" "a C type" } { "quot" { $quotation "( obj c-ptr n -- )" } } }
{ $description "Outputs a quotation which writes values of this C type to a C structure." }
{ $errors "Throws an error if the type does not exist." } ;
HELP: box-parameter
{ $values { "n" math:integer } { "ctype" string } }
{ $values { "n" math:integer } { "c-type" "a C type" } }
{ $description "Generates code for converting a C value stored at offset " { $snippet "n" } " from the top of the stack into a Factor object to be pushed on the data stack." }
{ $notes "This is an internal word used by the compiler when compiling callbacks." } ;
HELP: box-return
{ $values { "ctype" string } }
{ $values { "c-type" "a C type" } }
{ $description "Generates code for converting a C value stored in return registers into a Factor object to be pushed on the data stack." }
{ $notes "This is an internal word used by the compiler when compiling alien calls." } ;
HELP: unbox-return
{ $values { "ctype" string } }
{ $values { "c-type" "a C type" } }
{ $description "Generates code for converting a Factor value on the data stack into a C value to be stored in the return registers." }
{ $notes "This is an internal word used by the compiler when compiling callbacks." } ;

View File

@ -39,8 +39,8 @@ unboxer
{ rep initial: int-rep }
stack-align? ;
: <c-type> ( -- type )
\ c-type new ;
: <c-type> ( -- c-type )
\ c-type new ; inline
SYMBOL: c-types
@ -56,13 +56,14 @@ PREDICATE: c-type-word < word
UNION: c-type-name string word ;
! C type protocol
GENERIC: c-type ( name -- type ) foldable
GENERIC: c-type ( name -- c-type ) foldable
GENERIC: resolve-pointer-type ( name -- c-type )
M: word resolve-pointer-type
dup "pointer-c-type" word-prop
[ ] [ drop void* ] ?if ;
M: string resolve-pointer-type
dup "*" append dup c-types get at
[ nip ] [
@ -71,14 +72,14 @@ M: string resolve-pointer-type
[ resolve-pointer-type ] [ drop void* ] if
] if ;
: resolve-typedef ( name -- type )
: resolve-typedef ( name -- c-type )
dup c-type-name? [ c-type ] when ;
: parse-array-type ( name -- dims type )
: parse-array-type ( name -- dims c-type )
"[" split unclip
[ [ "]" ?tail drop string>number ] map ] dip ;
M: string c-type ( name -- type )
M: string c-type ( name -- c-type )
CHAR: ] over member? [
parse-array-type prefix
] [
@ -93,7 +94,7 @@ M: word c-type
: void? ( c-type -- ? )
{ void "void" } member? ;
GENERIC: c-struct? ( type -- ? )
GENERIC: c-struct? ( c-type -- ? )
M: object c-struct?
drop f ;
@ -169,33 +170,33 @@ M: c-type c-type-stack-align? stack-align?>> ;
M: c-type-name c-type-stack-align? c-type c-type-stack-align? ;
: c-type-box ( n type -- )
: c-type-box ( n c-type -- )
[ c-type-rep ] [ c-type-boxer [ "No boxer" throw ] unless* ] bi
%box ;
: c-type-unbox ( n ctype -- )
: c-type-unbox ( n c-type -- )
[ c-type-rep ] [ c-type-unboxer [ "No unboxer" throw ] unless* ] bi
%unbox ;
GENERIC: box-parameter ( n ctype -- )
GENERIC: box-parameter ( n c-type -- )
M: c-type box-parameter c-type-box ;
M: c-type-name box-parameter c-type box-parameter ;
GENERIC: box-return ( ctype -- )
GENERIC: box-return ( c-type -- )
M: c-type box-return f swap c-type-box ;
M: c-type-name box-return c-type box-return ;
GENERIC: unbox-parameter ( n ctype -- )
GENERIC: unbox-parameter ( n c-type -- )
M: c-type unbox-parameter c-type-unbox ;
M: c-type-name unbox-parameter c-type unbox-parameter ;
GENERIC: unbox-return ( ctype -- )
GENERIC: unbox-return ( c-type -- )
M: c-type unbox-return f swap c-type-unbox ;
@ -203,13 +204,13 @@ M: c-type-name unbox-return c-type unbox-return ;
: little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable
GENERIC: heap-size ( type -- size ) foldable
GENERIC: heap-size ( name -- size ) foldable
M: c-type-name heap-size c-type heap-size ;
M: abstract-c-type heap-size size>> ;
GENERIC: stack-size ( type -- size ) foldable
GENERIC: stack-size ( name -- size ) foldable
M: c-type-name stack-size c-type stack-size ;
@ -236,7 +237,7 @@ MIXIN: value-type
[ "Cannot write struct fields with this type" throw ]
] unless* ;
: array-accessor ( type quot -- def )
: array-accessor ( c-type quot -- def )
[
\ swap , [ heap-size , [ * >fixnum ] % ] [ % ] bi*
] [ ] make ;
@ -262,19 +263,19 @@ M: word typedef ( old new -- )
TUPLE: long-long-type < c-type ;
: <long-long-type> ( -- type )
: <long-long-type> ( -- c-type )
long-long-type new ;
M: long-long-type unbox-parameter ( n type -- )
M: long-long-type unbox-parameter ( n c-type -- )
c-type-unboxer %unbox-long-long ;
M: long-long-type unbox-return ( type -- )
M: long-long-type unbox-return ( c-type -- )
f swap unbox-parameter ;
M: long-long-type box-parameter ( n type -- )
M: long-long-type box-parameter ( n c-type -- )
c-type-boxer %box-long-long ;
M: long-long-type box-return ( type -- )
M: long-long-type box-return ( c-type -- )
f swap box-parameter ;
: define-deref ( name -- )
@ -286,13 +287,13 @@ M: long-long-type box-return ( type -- )
[ dup c-setter '[ _ heap-size <byte-array> [ 0 @ ] keep ] ] bi
(( value -- c-ptr )) define-inline ;
: define-primitive-type ( type name -- )
: define-primitive-type ( c-type name -- )
[ typedef ]
[ name>> define-deref ]
[ name>> define-out ]
tri ;
: if-void ( type true false -- )
: if-void ( c-type true false -- )
pick void? [ drop nip call ] [ nip call ] if ; inline
CONSTANT: primitive-types

View File

@ -1,6 +1,7 @@
USING: alien alien.c-types help.syntax help.markup libc kernel.private
byte-arrays math strings hashtables alien.syntax alien.strings sequences
io.encodings.string debugger destructors vocabs.loader ;
USING: alien alien.c-types help.syntax help.markup libc
kernel.private byte-arrays math strings hashtables alien.syntax
alien.strings sequences io.encodings.string debugger destructors
vocabs.loader classes.struct ;
IN: alien.data
HELP: <c-array>
@ -26,7 +27,7 @@ HELP: byte-array>memory
{ $warning "This word is unsafe. Improper use can corrupt memory." } ;
HELP: malloc-array
{ $values { "n" "a non-negative integer" } { "type" "a C type" } { "alien" alien } }
{ $values { "n" "a non-negative integer" } { "type" "a C type" } { "array" "a specialized array" } }
{ $description "Allocates an unmanaged memory block large enough to hold " { $snippet "n" } " values of a C type, then wraps the memory in a sequence object using " { $link <c-direct-array> } "." }
{ $notes "The appropriate specialized array vocabulary must be loaded; otherwise, an error will be thrown. The vocabulary can be loaded with the " { $link require-c-array } " word. See the " { $vocab-link "specialized-arrays" } " vocabulary for details on the underlying sequence type constructed." }
{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
@ -53,8 +54,8 @@ ARTICLE: "malloc" "Manual memory management"
$nl
"Allocating a C datum with a fixed address:"
{ $subsection malloc-object }
{ $subsection malloc-array }
{ $subsection malloc-byte-array }
{ $subsection malloc-file-contents }
"There is a set of words in the " { $vocab-link "libc" } " vocabulary which directly call C standard library memory management functions:"
{ $subsection malloc }
{ $subsection calloc }
@ -73,26 +74,31 @@ $nl
"You can copy a byte array to memory unsafely:"
{ $subsection byte-array>memory } ;
ARTICLE: "c-byte-arrays" "Passing data in byte arrays"
"Instances of the " { $link byte-array } " class can be passed to C functions; the C function receives a pointer to the first element of the array."
$nl
"Byte arrays can be allocated directly with a byte count using the " { $link <byte-array> } " word. However in most cases, instead of computing a size in bytes directly, it is easier to use a higher-level word which expects C type and outputs a byte array large enough to hold that type:"
{ $subsection <c-object> }
{ $subsection <c-array> }
ARTICLE: "c-pointers" "Passing pointers to C functions"
"The following Factor objects may be passed to C function parameters with pointer types:"
{ $list
{ "Instances of " { $link alien } "." }
{ "Instances of " { $link f } "; this is interpreted as a null pointer." }
{ "Instances of " { $link byte-array } "; the C function receives a pointer to the first element of the array." }
{ "Any data type which defines a method on " { $link >c-ptr } " that returns an instance of one of the above. This includes " { $link "classes.struct" } " and " { $link "specialized-arrays" } "." }
}
"The class of primitive C pointer types:"
{ $subsection c-ptr }
"A generic word for converting any object to a C pointer; user-defined types may add methods to this generic word:"
{ $subsection >c-ptr }
"More about the " { $link alien } " type:"
{ $subsection "aliens" }
{ $warning
"The Factor garbage collector can move byte arrays around, and code passing byte arrays to C must obey important guidelines. See " { $link "byte-arrays-gc" } "." }
{ $see-also "c-arrays" } ;
"The Factor garbage collector can move byte arrays around, and code passing byte arrays, or objects backed by byte arrays, must obey important guidelines. See " { $link "byte-arrays-gc" } "." } ;
ARTICLE: "c-data" "Passing data between Factor and C"
"Two defining characteristics of Factor are dynamic typing and automatic memory management, which are somewhat incompatible with the machine-level data model exposed by C. Factor's C library interface defines its own set of C data types, distinct from Factor language types, together with automatic conversion between Factor values and C types. For example, C integer types must be declared and are fixed-width, whereas Factor supports arbitrary-precision integers."
$nl
"Furthermore, Factor's garbage collector can move objects in memory; for a discussion of the consequences, see " { $link "byte-arrays-gc" } "."
{ $subsection "c-types-specs" }
{ $subsection "c-byte-arrays" }
{ $subsection "c-pointers" }
{ $subsection "malloc" }
{ $subsection "c-strings" }
{ $subsection "c-arrays" }
{ $subsection "c-out-params" }
"Important guidelines for passing data in byte arrays:"
{ $subsection "byte-arrays-gc" }
@ -100,12 +106,10 @@ $nl
{ $subsection POSTPONE: C-ENUM: }
"C types can be aliased for convenience and consitency with native library documentation:"
{ $subsection POSTPONE: TYPEDEF: }
"New C types can be defined:"
{ $subsection "c-structs" }
{ $subsection "c-unions" }
"A utility for defining " { $link "destructors" } " for deallocating memory:"
{ $subsection "alien.destructors" }
{ $see-also "aliens" } ;
"C struct and union types can be defined with " { $link POSTPONE: STRUCT: } " and " { $link POSTPONE: UNION: } ". See " { $link "classes.struct" } " for details. For passing arrays to and from C, use the " { $link "specialized-arrays" } " vocabulary." ;
HELP: malloc-string
{ $values { "string" string } { "encoding" "an encoding descriptor" } { "alien" c-ptr } }
{ $description "Encodes a string together with a trailing null code point using the given encoding, and stores the resulting bytes in a freshly-allocated unmanaged memory block." }

View File

@ -29,7 +29,7 @@ GENERIC: <c-direct-array> ( alien len c-type -- array )
M: c-type-name <c-direct-array>
c-direct-array-constructor execute( alien len -- array ) ; inline
: malloc-array ( n type -- alien )
: malloc-array ( n type -- array )
[ heap-size calloc ] [ <c-direct-array> ] 2bi ; inline
: (malloc-array) ( n type -- alien )

View File

@ -7,7 +7,7 @@ ARTICLE: "bit-arrays" "Bit arrays"
$nl
"Bit array words are in the " { $vocab-link "bit-arrays" } " vocabulary."
$nl
"Bit arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-byte-arrays" } "."
"Bit arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-pointers" } "."
$nl
"Bit arrays form a class of objects:"
{ $subsection bit-array }

View File

@ -95,9 +95,36 @@ HELP: struct
HELP: struct-class
{ $class-description "The metaclass of all " { $link struct } " classes." } ;
ARTICLE: "classes.struct" "Struct classes"
{ $link struct } " classes are similar to " { $link tuple } "s, but their slots exhibit value semantics, and they are backed by a contiguous structured block of memory. Structs can be used for structured access to C memory or Factor byte arrays and for passing struct values in and out of the FFI. Struct types are defined using a syntax similar to tuple syntax:"
ARTICLE: "classes.struct.examples" "Struct class examples"
"A struct with a variety of fields:"
{ $code
"USING: alien.c-types classes.struct ;"
""
"STRUCT: test-struct"
" { i int }"
" { chicken char[16] }"
" { data void* } ;"
}
"Creating a new instance of this struct, and printing out:"
{ $code "test-struct <struct> ." }
"Creating a new instance with slots initialized from the stack:"
{ $code
"USING: libc specialized-arrays ;"
"SPECIALIZED-ARRAY: char"
""
"42"
"\"Hello, chicken.\" >char-array"
"1024 malloc"
"test-struct <struct-boa> ."
} ;
ARTICLE: "classes.struct.define" "Defining struct classes"
"Struct classes are defined using a syntax similar to the " { $link POSTPONE: TUPLE: } " syntax for defining tuple classes:"
{ $subsection POSTPONE: STRUCT: }
"Union structs are also supported, which behave like structs but share the same memory for all the slots."
{ $subsection POSTPONE: UNION-STRUCT: } ;
ARTICLE: "classes.struct.create" "Creating instances of structs"
"Structs can be allocated with " { $link new } "- and " { $link boa } "-like constructor words. Additional words are provided for building structs from C memory and from existing buffers:"
{ $subsection <struct> }
{ $subsection <struct-boa> }
@ -106,10 +133,40 @@ ARTICLE: "classes.struct" "Struct classes"
"When the contents of a struct will be immediately reset, faster primitive words are available that will create a struct without initializing its contents:"
{ $subsection (struct) }
{ $subsection (malloc-struct) }
"Structs have literal syntax like tuples:"
{ $subsection POSTPONE: S{ }
"Union structs are also supported, which behave like structs but share the same memory for all the type's slots."
{ $subsection POSTPONE: UNION-STRUCT: }
;
"Structs have literal syntax, similar to " { $link POSTPONE: T{ } " for tuples:"
{ $subsection POSTPONE: S{ } ;
ARTICLE: "classes.struct.c" "Passing structs to C functions"
"Structs can be passed and returned by value, or by reference."
$nl
"If a parameter is declared with a struct type, the parameter is passed by value. To pass a struct by reference, declare a parameter with a pointer to struct type."
$nl
"If a C function is declared as returning a struct type, the struct is returned by value, and wrapped in an instance of the correct struct class automatically. If a C function is declared as returning a pointer to a struct, it will return an " { $link alien } " instance. This is because there is no way to distinguish between a pointer to a single struct and a pointer to an array of zero or more structs. It is up to the caller to wrap it in a struct, or a specialized array of structs, respectively."
$nl
"An example of a struct declaration:"
{ $code
"USING: alien.c-types classes.struct ;"
""
"STRUCT: Point"
" { x int }"
" { y int }"
" { z int } ;"
}
"A C function which returns a struct by value:"
{ $code
"USING: alien.syntax ;"
"FUNCTION: Point give_me_a_point ( char* description ) ;"
}
"A C function which takes a struct parameter by reference:"
{ $code
"FUNCTION: void print_point ( Point* p ) ;"
} ;
ARTICLE: "classes.struct" "Struct classes"
{ $link struct } " classes are similar to " { $link tuple } "s, but their slots exhibit value semantics, and they are backed by a contiguous structured block of memory. Structs can be used for structured access to C memory or Factor byte arrays and for passing struct values in and out of the FFI."
{ $subsection "classes.struct.examples" }
{ $subsection "classes.struct.define" }
{ $subsection "classes.struct.create" }
{ $subsection "classes.struct.c" } ;
ABOUT: "classes.struct"

View File

@ -311,7 +311,7 @@ HELP: textual-list
{ $values { "seq" "a sequence" } { "quot" { $quotation "( elt -- )" } } }
{ $description "Applies the quotation to each element of the sequence, printing a comma between each pair of elements." }
{ $examples
{ $example "USING: help.markup io ;" "{ \"fish\" \"chips\" \"salt\" } [ write ] textual-list" "fish, chips, salt" }
{ $example "USING: help.markup io namespaces ;" "last-element off" "{ \"fish\" \"chips\" \"salt\" } [ write ] textual-list" "fish, chips, salt" }
} ;
HELP: $links

View File

@ -21,6 +21,45 @@ ARTICLE: "specialized-array-words" "Specialized array words"
"Behind the scenes, these words are placed in a vocabulary named " { $snippet "specialized-arrays.instances.T" } ", however this vocabulary should not be placed in a " { $link POSTPONE: USING: } " form directly. Instead, always use " { $link POSTPONE: SPECIALIZED-ARRAY: } ". This ensures that the vocabulary can get generated the first time it is needed." ;
ARTICLE: "specialized-array-c" "Passing specialized arrays to C functions"
"If a C function is declared as taking a parameter with a pointer or an array type (for example, " { $snippet "float*" } " or " { $snippet "int[3]" } "), instances of the relevant specialized array can be passed in."
$nl
"C type specifiers for array types are documented in " { $link "c-types-specs" } "."
$nl
"Here is an example; as is common with C functions, the array length is passed in separately, since C does not offer a runtime facility to determine the array length of a base pointer:"
{ $code
"USING: alien.syntax specialized-arrays ;"
"SPECIALIZED-ARRAY: int"
"FUNCTION: void process_data ( int* data, int len ) ;"
"int-array{ 10 20 30 } dup length process_data"
}
"Literal specialized arrays, as well as specialized arrays created with " { $snippet "<T-array>" } " and " { $snippet ">T-array" } " are backed by a " { $link byte-array } " in the Factor heap, and can move as a result of garbage collection. If this is unsuitable, the array can be allocated in unmanaged memory instead."
$nl
"In the following example, it is presumed that the C library holds on to a pointer to the array's data after the " { $snippet "init_with_data()" } " call returns; this is one situation where unmanaged memory has to be used instead. Note the use of destructors to ensure the memory is deallocated after the block ends:"
{ $code
"USING: alien.syntax specialized-arrays ;"
"SPECIALIZED-ARRAY: float"
"FUNCTION: void init_with_data ( float* data, int len ) ;"
"FUNCTION: float compute_result ( ) ;"
"["
" 100 malloc-float-array &free"
" dup length init_with_data"
" compute_result"
"] with-destructors"
}
"Finally, sometimes a C library returns a pointer to an array in unmanaged memory, together with a length. In this case, a specialized array can be constructed to view this memory using " { $snippet "<direct-T-array>" } ":"
{ $code
"USING: alien.c-types classes.struct ;"
""
"STRUCT: device_info"
" { id int }"
" { name char* } ;"
""
"FUNCTION: void get_device_info ( int* length ) ;"
""
"0 <int> [ get_device_info ] keep <direct-int-array> ."
}
"For a full discussion of Factor heap allocation versus unmanaged memory allocation, see " { $link "byte-arrays-gc" } "."
$nl
"Each specialized array has a " { $slot "underlying" } " slot holding a " { $link byte-array } " with the raw data. Passing a specialized array as a parameter to a C function call will automatically extract the underlying data. To get at the underlying data directly, call the " { $link >c-ptr } " word on a specialized array." ;
ARTICLE: "specialized-array-math" "Vector arithmetic with specialized arrays"
@ -42,7 +81,7 @@ ARTICLE: "specialized-arrays" "Specialized arrays"
$nl
"A specialized array type needs to be generated for each element type. This is done with a parsing word:"
{ $subsection POSTPONE: SPECIALIZED-ARRAY: }
"This parsing word adds new words to the search path:"
"This parsing word adds new words to the search path, documented in the next section."
{ $subsection "specialized-array-words" }
{ $subsection "specialized-array-c" }
{ $subsection "specialized-array-math" }

View File

@ -261,7 +261,6 @@ $nl
"C library interface words are found in the " { $vocab-link "alien" } " vocabulary."
{ $warning "C does not perform runtime type checking, automatic memory management or array bounds checks. Incorrect usage of C library functions can lead to crashes, data corruption, and security exploits." }
{ $subsection "loading-libs" }
{ $subsection "aliens" }
{ $subsection "alien-invoke" }
{ $subsection "alien-callback" }
{ $subsection "c-data" }

View File

@ -6,7 +6,7 @@ ARTICLE: "byte-arrays" "Byte arrays"
$nl
"Byte array words are in the " { $vocab-link "byte-arrays" } " vocabulary."
$nl
"Byte arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-byte-arrays" } "."
"Byte arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-pointers" } "."
$nl
"Byte arrays form a class of objects."
{ $subsection byte-array }