For Development HEAD DRAFTSearch (procedure/syntax/module):

9.22 gauche.native-type - ネイティブタイプユーティリティ

Module: gauche.native-type

This module provides a type infrastructure to communicate with the “native”, or “close to the metal” layer. Examples include foreign function interface (FFI) and structured binary data access.

Basic native types are built-in (see ネイティブタイプ). This module adds constructors for derived or aggregate types (such as arrays and structs), endian-specified types, conversions between native type objects and compact signatures, and so on.

This module also provides native handles, via which you access native data from Scheme world (see Native handles).


9.22.1 Derived and aggregate native types

We have subclasses of <native-type>, which are classes of individual derived or aggregate native types. For example, “pointer to int” native type is an instance of <c-pointer> class. Note that <c-pointer> itself is not an instance of <native-type>.

C pointers

Class: <c-pointer>

A class of native types representing pointers. Can be created with make-c-pointer-type, or from a signature with native-type (e.g. (native-type 'int*), see Native type signature).

Note: At the moment, we don’t keep track of quoalifiers such as const or volatile, but their support may be added in future.

A native handle with a C pointer type can be “dereferenced” with native* (see Native handles).

Function: make-c-pointer-type pointee-type

{gauche.native-type} The argument must be an native type instance. Returns an native type represents a pointer to the pointee-type.

(make-c-pointer-type <int>)
  ⇒ #<c-pointer <int*>>

(make-c-pointer-type (make-c-pointer-type <int>))
  ⇒ #<c-pointer <int**>>
Function: c-pointer-type-pointee c-pointer-type

{gauche.native-type} Returns the pointee type of the given c-pointer type.

(c-pointer-type-pointee (make-c-pointer-type <int>))
  ⇒ #<native-type <int>>

C arrays

Class: <c-array>

{gauche.native-type} A class of native types representing C-style arrays. Can be created with make-c-array-type, or from a signature with native-type (e.g. (native-type '(.array int (10))), see Native type signature).

Arrays can have more than one dimensions. Elements with consectuve last indexes are laid adjacent on memory. The length of the first dimension can be left unspecified (we use * as a placeholder), just like C array such as int a[][10][3].

An element, or a subarray, of an array represented by a native handle with a C array type can be accessed with native-aref (see Native handles).

Function: make-c-array-type element-type element-type dimensions

{gauche.native-type} Creates a C array type, whose elements are of type element-type, which must be a native type.

The dimensions argument must be a list of non-negative exact integers, except that the first element may be a symbol *. They specify the lengths of each dimension of the array. Each index of dimensions starts with 0. * in the first dimension indicates the length is unspecified.

Function: c-array-type-dimensions c-array-type

{gauche.native-type} Returns a list of lengths of dimensions of c-array-type.

C functions

Class: <c-function>

{gauche.native-type} A class of native types representing C function types. Can be created with make-c-function-type, or from a signature with native-type (e.g. (native-type '(.function (int int) ::int)), see Native type signature).

Instances of <c-function> describe the signature of a C function: its return type, argument types, and whether it accepts variable arguments.

A native handle with a <c-function> type can be cast to and from a pointer-to-function type with cast-handle (see Native handles).

Function: make-c-function-type return-type argument-type-list

{gauche.native-type} Returns a native type representing a C function that returns return-type and takes arguments of the types listed in argument-type-list. Both return-type and each element of argument-type-list must be native type instances, with an exception below.

The last element of argument-type-list can be the symbol ..., and then the resulting type represents a variadic function (like C’s ... in int printf(const char*, …)). The ... marker is not a native type and is not included in the result of c-function-type-argument-types.

(make-c-function-type <int> `(,<int> ,<double>))
  ⇒ #<c-function  int double -> int>

(make-c-function-type <int> `(,<int> ...))
  ⇒ #<c-function  int ... -> int>

(c-function-type-argument-types (make-c-function-type <int> `(,<int> ...)))
  ⇒ (#<native-type <int>>)

(c-function-type-variadic? (make-c-function-type <int> `(,<int> ...)))
  ⇒ #t
Function: c-function-type-return-type c-function-type

{gauche.native-type} Returns the return type of c-function-type as a native type instance.

Function: c-function-type-argument-types c-function-type

{gauche.native-type} Returns the list of argument types of c-function-type. Each element is a native type instance. The variadic marker ... is not included; use c-function-type-variadic? to check for variadic functions.

Function: c-function-type-variadic? c-function-type

{gauche.native-type} Returns #t if c-function-type represents a variadic function (i.e., it was created with ... as the last element of the argument-type list), #f otherwise.

C structs and unions

Class: <c-struct>
Class: <c-union>

{gauche.native-type} A class of native types representing C struct and union types, respectively. Can be created with make-c-struct-type and make-c-union-type, or from a signature with native-type (e.g. (native-type '(.struct t (a::int b::char))), see Native type signature).

Function: make-c-struct-type tag fields
Function: make-c-union-type tag fields

{gauche.native-type} Returns a native type representing a C struct type or a C union type. tag can be a symbol representing the struct/union tag, or #f for untagged struct/union.

fields is a list of (symbol type), where symbol names the field’s name, and type for its type. type must be an instance of a native type.

When a struct/union type is constructed, its total size and each field’s offset are computed (in unions, all the offsets are 0).

Function: c-struct/union-type-tag c-struct/union-type

{gauche.native-type} Returns the tag (symbol) of c-struct/union-type. If the type is untagged, #f is returned.

Function: c-struct/union-type-field-names c-struct/union-type

{gauche.native-type} Returns a list of field names (symbols) of c-struct/union-type.

Function: c-struct/union-type-field-type c-struct/union-type field-name
Function: c-struct/union-type-field-offset c-struct/union-type field-name

{gauche.native-type} Returns the type and the byte offset of field-name (symbol) of c-struct/union-type.

9.22.1.1 Predicates

Function: c-pointer-type? obj
Function: c-array-type? obj
Function: c-function-type? obj
Function: c-struct-type? obj
Function: c-union-type? obj

{gauche.native-type} Returns #t if obj is an instance of <c-pointer>, <c-array>, c-function>, c-struct, or <c-union>, and #f otherwise, respectively.

Function: c-pointer-like-type? obj

{gauche.native-type} Returns #t if obj is either a C pointer type, a C array type, or a C function type. Handles of those types can be “casted” to a pointer type, following the C semantics. See cast-handle for the details (see Native handles).

Function: c-aggregate-type? obj

{gauche.native-type} Returns #t if obj is either a C array type, a C struct type, or a C union type.

Function: c-struct/union-type? obj

{gauche.native-type} Returns #t if obj is either a C struct type, or a C union type.


9.22.2 Representation-specific types

Primitive native types such as <int16> read/write memory with the system’s native endianness. For FFI it is fine. However, if you read/write binary data for exchanging between systems, you need to explicitly specify the endianness.

We have native types for that purpose.

Native type: <int16-be>
Native type: <int16-le>
Native type: <int32-be>
Native type: <int32-le>
Native type: <int64-be>
Native type: <int64-le>
Native type: <uint16-be>
Native type: <uint16-le>
Native type: <uint32-be>
Native type: <uint32-le>
Native type: <uint64-be>
Native type: <uint64-le>
Native type: <float-be>
Native type: <float-le>
Native type: <double-be>
Native type: <double-le>

{gauche.native-type} These native types accesses binary data as the specified numeric type, and the specified endianncess (-be for big-endian, -le for little endian).

The endianness is only considered when reading from or writing to memory through native handles (with native* etc, see Native handles). In other words, these types only makes sense when they are used within derived or aggregate types.


9.22.3 Native type signature

A native type signature is a compact S-expression description of a native type. It lets you specify pointer, array, struct, union, and function types without explicitly calling the corresponding constructors such as make-c-pointer-type.

The procedure native-type can parse a signature and returns the native type instance it denotes; native-type->signature performs the inverse conversion. Signatures are also recognized in some other places where a native type is expected—for example, in struct/union field type declarations within .struct and .union signature forms (so compound types can be written without first naming each piece).

The signature format has been used in Gauche-C interface for long time (stubs and CiSE), though hasn’t been documented well. Because of its origin to transfer C type declarations to S-expression, it may feel C-centric.

Primitive types

A bare symbol whose name matches a built-in C type name denotes the corresponding primitive native type. Recognized names follow the C spelling, e.g. int, u_int, short, u_short, long, u_long, char, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, size_t, ssize_t, ptrdiff_t, off_t, intptr_t, uintptr_t, float, double, and void. See ネイティブタイプ for the corresponding type instances and what Scheme values they accept.

C’s char denotes the native type <c-char>, for <char> is used for Gauche’s character type. <c-char> is mapped to a Scheme character with unicode range U+0000 to U+00FF. If the C routine uses char as a byte-sized numeric value, use int8_t or uint8_t (depending on signedness) instead.

The pseudo-name c-string denotes the <c-string> type (NUL-terminated C string). This special name is provided because C type const char * may simply mean a pointer to byte-sized numeric data, thus ambiguous.

pThe endian-specified types listed in Representation-specific types are also accepted, by their underscore-separated names: int16_le, int16_be, uint16_le, uint16_be, and likewise for the 32-bit and 64-bit integer types and for float and double.

Pointer types

A symbol whose name ends with one or more asterisks denotes a pointer type; each trailing asterisk wraps the rest of the type in one additional layer of <c-pointer>. Thus int* is equivalent to (make-c-pointer-type <int>), char** is a pointer to a pointer to <c-char>, and so on.

C-style multi-token forms are also accepted as a list of symbols. The list is normalized by stripping any const tokens and concatenating the rest into a single symbol. Therefore (char *), (char const*), (const char*), (int * *), and (int** *) are all valid. The form (const type) is also accepted, with const currently ignored.

(We do not yet track const or volatile qualifiers on the resulting native type; they are silently dropped. Support may be added in the future.)

Array types

(.array element-type (dim ...))

Denotes a C-style array. element-type is itself a native type signature. Each dim is a non-negative exact integer, except that the leftmost dim may be the symbol * to indicate an unspecified leading dimension (as in C’s int a[][3][4]). Multiple dimensions describe a multi-dimensional array, with elements that share leading indices laid out adjacently in memory (the last index varies fastest).

Struct and union types

(.struct tag (field-spec ...))
(.struct (field-spec ...))
(.union  tag (field-spec ...))
(.union  (field-spec ...))

Denote a C struct or union type. tag, when given, is a symbol that names the struct/union tag; the second form of each pair (with no tag) denotes an anonymous struct/union.

Each field-spec has the form name::type, using the typed-variable notation common across Gauche. name is a symbol naming the field, and type is itself a native type signature, so fields may be of compound type as well. For the convenience, the delimiter :: may be concatenated to name and/or type– for example, a::int and a :: int are equivalent.

Function types

(.function (arg-type ...) return-type)
(.function (arg-type ... ...) return-type)

Denotes a C function type. Each arg-type and return-type is itself a native type signature. If the last arg-type is the literal symbol ..., the resulting type is variadic (corresponding to C’s trailing ...); the ... marker is not itself a type, and is not included in the argument-type list returned by c-function-type-argument-types. Use c-function-type-variadic? to test for variadicity.

Pass-through

If the argument is already an instance of <native-type>, native-type returns it unchanged. This makes it convenient for higher-level routines to accept either a signature or a previously constructed type instance.

Notably, you can emulate C’s typedef by assigning native type to a variable, and inserting it in another type signature:

(define foo (.struct foo (a::int b::int)))

(native-type `(.array ,foo (10))) ⇒ #<c-array struct foo(10)>

Examples

(native-type 'int)
  ⇒ #<native-type <int>>

(native-type 'int*)
  ⇒ #<c-pointer <int*>>

(native-type 'char**)
  ⇒ #<c-pointer <c-char**>>

(native-type '(char const *))
  ⇒ #<c-pointer <c-char*>>

(native-type 'c-string)
  ⇒ #<native-type <c-string>>

(native-type '(.array int (3 4)))
  ⇒ #<c-array <int>(3 4)>

(native-type '(.array int (* 3)))
  ⇒ #<c-array <int>(* 3)>

(native-type '(.struct point (x::double y::double)))
  ⇒ #<c-struct struct point>

(native-type '(.union v (i::int f::float)))
  ⇒ #<c-union union v>

(native-type '(.function (int int) double))
  ⇒ #<c-function <int> <int> -> <double>>

(native-type '(.function (char* ...) int))
  ⇒ #<c-function <c-char*> ... -> <int>>
Function: native-type signature-or-type

{gauche.native-type} The argument must be an S-expression type signature or a native type instance. If it is a type signature, a native type instance denoted by the type signature is returned. If the argument is already a native type instance, it is returned as is.

See above for the specification of a native type signature.

Function: native-type->signature native-type

{gauche.native-type} Returns a native type signature that denotes the given native type.


9.22.4 Native handles

A native handle is a handle through which you can access native data. Native handles may be returned from a foreign function call, or you can create one from a binary buffer. C pointers, arrays, structs, and unions to be passed to and from foreign functions are reprensed by native handles.

Native handle class and predicates

Class: <native-handle>

{gauche.native-type}

Instance Variable of <native-handle>: type
Function: c-pointer-handle? obj

{gauche.native-type}

Function: c-function-handle? obj

{gauche.native-type}

Function: c-array-handle? obj

{gauche.native-type}

Function: c-struct-handle? obj
Function: c-union-handle? obj

{gauche.native-type}

Function: c-aggregate-handle? obj

{gauche.native-type}

Function: c-pointer-like-handle? obj

{gauche.native-type}

Accessing through native handles

Function: native* handle

{gauche.native-type}

Function: (setter native*) handle val

{gauche.native-type}

Function: native-aref handle index

{gauche.native-type}

Function: (setter native-aref) handle index val

{gauche.native-type}

Function: native. handle slot

{gauche.native-type}

Function: (setter native.) handle slot :optional type

{gauche.native-type}

Function: native-> handle slot

{gauche.native-type}

Function: (setter native->) handle slot :optional type

{gauche.native-type}

Pointer handle operations

Function: cast-handle type handle :optional offset

{gauche.native-type}

Function: c-pointer-compare handle-a handle-b

{gauche.native-type}

Function: c-pointer=? handle-a handle-b
Function: c-pointer<? handle-a handle-b
Function: c-pointer<=? handle-a handle-b
Function: c-pointer>? handle-a handle-b
Function: c-pointer>=? handle-a handle-b

{gauche.native-type}

Aggregate handle operations

Function: c-memwise-compare handle-a handle-b

{gauche.native-type}

Creating a native handle

Function: null-pointer-handle

{gauche.native-type}

Function: null-pointer-handle? obj

{gauche.native-type}

Function: uvector->hative-handle uv type :optional offset

{gauche.native-type}



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT