~ chicken-core (chicken-5) 613c7ca8e2e6a25c7c0d85844c0175198808a8a9
commit 613c7ca8e2e6a25c7c0d85844c0175198808a8a9 Author: Jim Ursetto <zbigniewsz@gmail.com> AuthorDate: Wed Jan 23 23:42:19 2013 -0600 Commit: Jim Ursetto <zbigniewsz@gmail.com> CommitDate: Wed Jan 23 23:42:26 2013 -0600 manual/Foreign type specifiers: merge changes from wiki (content expansion, <type> tag) diff --git a/manual/Foreign type specifiers b/manual/Foreign type specifiers index 352903ce..090a1013 100644 --- a/manual/Foreign type specifiers +++ b/manual/Foreign type specifiers @@ -1,220 +1,316 @@ [[tags: manual]] +[[toc:]] == Foreign type specifiers -Here is a list of valid foreign type specifiers: +Here is a list of valid foreign type specifiers for use in [[Accessing external objects|accessing external objects]]. -=== scheme-object +=== Void -An arbitrary Scheme data object (immediate or non-immediate). +<type>void</type> -=== bool +Specifies an undefined return value. Not allowed as argument type. -As argument: any value ({{#f}} is false, anything else is true). +=== Boolean + +<type>bool</type> + +As argument: any value ({{#f}} is false (zero), anything else is true (non-zero). As result: anything different from 0 and the {{NULL}} pointer is {{#t}}. -=== byte unsigned-byte +This type maps to {{int}} in both C and C++. -A byte. +=== Characters -=== char unsigned-char +<type>char</type><br> +<type>unsigned-char</type><br> -A character. +A signed or unsigned character. -=== short unsigned-short +As an argument, the input Scheme character is cast to C {{char}} or +{{unsigned char}}, resulting in an 8-bit value. A Scheme character +with an integer value outside 0-127 (signed) or 0-255 (unsigned) will +be silently truncated to fit; in other words, don't feed it +UTF-8 data. -A short integer number. +As a return type, accepts any valid Unicode code point; the return +type is treated as a C int, and converted to a Scheme character. -=== int unsigned-int int32 unsigned-int32 +=== Integers -An small integer number in fixnum range (at least 30 bit). +<type>byte</type><br> +<type>unsigned-byte</type><br> -=== integer unsigned-integer integer32 unsigned-integer32 integer64 unsigned-integer64 +An 8-bit integer value in range -128 - 127 (byte) or 0 - 255 (unsigned +byte). Values are cast to and from C {{char}} or {{unsigned char}} +type, so values outside this 8-bit range will be unceremoniously +truncated. -Either a fixnum or a flonum in the range of a (unsigned) machine ''int'' -or with 32/64 bit width. +<type>short</type><br> +<type>unsigned-short</type><br> -=== long unsigned-long +A short integer number in 16-bit range. Maps to C {{short}} or +{{unsigned short}}. -Either a fixnum or a flonum in the range of a (unsigned) machine ''long'' -or with 32 bit width. +<type>int</type><br> +<type>unsigned-int</type><br> +<type>int32</type><br> +<type>unsigned-int32</type><br> -=== float double +An integer number in fixnum range (-1073741824 to 1073741823, i.e. 31 +bit signed). {{unsigned-int}} further restricts this range to 30 bit +unsigned (0 to 1073741823). {{int}} maps to C type {{int}} and +{{int32}} maps to {{int32_t}}. -A floating-point number. If an exact integer is passed as an argument, -then it is automatically converted to a float. +As an argument type, these expect a fixnum value, and as a return type +they return a fixnum. Values outside the ranges prescribed above are +silently truncated; you should use e.g. {{integer}} if you need the full +32-bit range. Note: {{int32}} is not recognized as an argument type +prior to Chicken 4.7.2. -=== number +Notes for 64-bit architectures: -A floating-point number. Similar to {{double}}, but when used as a result type, -then either an exact integer or a floating-point number is returned, depending -on whether the result fits into an exact integer or not. +* C's {{int}} is 32 bits on most 64-bit systems +([[http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models|LP64]]), +so {{int}} and {{int32}} are functionally (if not semantically) equivalent. -=== symbol +* The fixnum type is larger than 32 bits and consequently the entire +signed or unsigned 32-bit range is available for this type on 64-bit +systems. However, for compatibility with 32-bit systems it is +probably unwise to rely on this. If you need a 32-bit range, you +should use (unsigned) {{integer}} or {{integer32}}. -A symbol, which will be passed to foreign code as a zero-terminated string. +<type>integer</type><br> +<type>unsigned-integer</type><br> +<type>integer32</type><br> +<type>unsigned-integer32</type><br> -When declared as the result of foreign code, the result should be a string and -a symbol with the same name will be interned in the symbol table (and returned -to the caller). +A fixnum or integral flonum, mapping to {{int}} or {{int32_t}} or +their unsigned variants. When outside of fixnum range the value will +overflow into a flonum. -=== scheme-pointer +C's {{int}} is 32 bits on most 64-bit systems +([[http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models|LP64]]), +so {{integer}} and {{integer32}} are functionally (if not semantically) equivalent. -An untyped pointer to the contents of a non-immediate Scheme object (not -allowed as return type). The value {{#f}} is also allowed and is passed as a -{{NULL}} pointer. +<type>integer64</type><br> +<type>unsigned-integer64</type> -Don't confuse this type with {{(c-pointer ...)}} which means something -different (a machine-pointer object). +A fixnum or integral flonum, mapping to {{int64_t}} or {{uint64_t}}. +When outside of fixnum range the value will overflow into a flonum. -{{scheme-pointer}} is typically used to get a pointer to the raw byte content of strings and blobs. But if you pass in a SRFI-4 vector, you will get a pointer to a blob object (''not'' the blob's contents), which is almost certainly wrong. Instead, convert to a blob beforehand, or use a SRFI-4 specific type. +On a 32-bit system, the effective precision of this type is 52 bits +plus the sign bit, as it is stored in a {{double}} flonum. (In other +words, numbers between 2^52 and 2^64-1 can be represented but there are +gaps in the sequence; the same goes for their negative counterparts.) +On a 64-bit system the range is 62 bits plus the sign bit, the +maximum range of a fixnum. (Numbers between 2^62 and 2^64-1 have gaps.) -=== nonnull-scheme-pointer +{{unsigned-integer64}} is not valid as a return type until Chicken 4.6.4. -As {{scheme-pointer}}, but guaranteed not to be {{#f}}. +<type>long</type><br> +<type>unsigned-long</type> -Don't confuse this type with {{(nonnull-c-pointer ...)}} which means something -different (a machine-pointer object). +Either a fixnum or a flonum in the range of an (unsigned) machine ''long''. +Similar to {{integer32}} on 32-bit systems or {{integer64}} on 64-bit. -=== c-pointer +=== Floating-point -An untyped operating-system pointer or a locative. The value {{#f}} is also -allowed and is passed as a {{NULL}} pointer. If uses as the type of -a return value, a {{NULL}} pointer will be returned as {{#f}}. +<type>float</type><br> +<type>double</type> -=== nonnull-c-pointer +A floating-point number. If an exact integer is passed as an argument, +then it is automatically converted to a float. -As {{c-pointer}}, but guaranteed not to be {{#f/NULL}}. +<type>number</type> -=== pointer-vector +A floating-point number. Similar to {{double}}, but when used as a result type, +then either an exact integer or a floating-point number is returned, depending +on whether the result fits into an exact integer or not. -A vector of foreign pointer objects. {{#f}} is allowed and passed as a -{{NULL}} pointer. +=== Strings -=== nonnull-pointer-vector +<type>c-string</type><br> +<type>nonnull-c-string</type> -As {{pointer-vector}}, but guaranteed not to be {{#f/NULL}}. +A zero-terminated C string. The argument value {{#f}} is allowed and +is passed as a {{NULL}} pointer; similarly, a NULL pointer is returned +as {{#f}}. Note that the string contents are copied into (automatically +managed) temporary storage with a zero byte appended when passed as an +argument. Also, a return value of this type is copied into garbage +collected memory using {{strcpy(3)}}. -=== blob +For the {{nonnull-}} variant, passing {{#f}} will raise an exception, and returning +a NULL pointer will result in undefined behavior (e.g. a segfault). -A blob object, passed as a pointer to its contents. Arguments of type {{blob}} -may optionally be {{#f}}, which is passed as a NULL pointer. +<type>c-string*</type><br> +<type>nonnull-c-string*</type> -This is not allowed as a return type. +Similar to {{c-string}} and {{nonnull-c-string}}, but if used as a result type, the pointer +returned by the foreign code will be freed (using the C library's {{free(3)}}) +after copying. This type specifier is not valid as a result type for callbacks +defined with {{define-external}}. -=== nonnull-blob +<type>unsigned-c-string</type><br> +<type>nonnull-unsigned-c-string</type><br> +<type>unsigned-c-string*</type><br> +<type>nonnull-unsigned-c-string*</type><br> -As {{blob}}, but guaranteed not to be {{#f}}. +Same as {{c-string}}, {{nonnull-c-string}}, etc. but mapping to C's +{{unsigned char *}} type. -=== u8vector -=== u16vector -=== u32vector -=== s8vector -=== s16vector -=== s32vector -=== f32vector -=== f64vector +<type>c-string-list</type><br> +<type>c-string-list*</type> -A SRFI-4 number-vector object, passed as a pointer to its contents. +Takes a pointer to an array of C strings terminated by a {{NULL}} pointer and +returns a list of strings. The starred version {{c-string-list*}} also releases +the storage of each string and the pointer array afterward using {{free(1)}}. -These type specifiers are not allowed as return types. +Only valid as a result type, and can only be used with non-callback functions. -=== nonnull-u8vector -=== nonnull-u16vector -=== nonnull-u32vector -=== nonnull-s8vector -=== nonnull-s16vector -=== nonnull-s32vector -=== nonnull-f32vector -=== nonnull-f64vector +<type>symbol</type> -As {{u8vector ...}}, but guaranteed not to be {{#f}}. +A symbol, which will be passed to foreign code as a zero-terminated string. -=== c-string +When declared as the result of foreign code, the result should be a string and +a symbol with the same name will be interned in the symbol table (and returned +to the caller). Attempting to return a NULL string will raise an exception. -A C string (zero-terminated). The value {{#f}} is also allowed and is passed as -a {{NULL}} pointer. If uses as the type of a return value, a {{NULL}} pointer -will be returned as {{#f}}. Note that the string is copied (with a zero-byte -appended) when passed as an argument to a foreign function. Also a return value -of this type is copied into garbage collected memory. +=== Bytevectors -=== nonnull-c-string +<type>blob</type><br> +<type>nonnull-blob</type> -As {{c-string}}, but guaranteed not to be {{#f/NULL}}. +A blob object, passed as a pointer to its contents. Permitted only as +argument type, not return type. -=== [nonnull-] c-string* +Arguments of type {{blob}} may optionally be {{#f}}, which is passed +as a NULL pointer. For the {{nonnull-}} variant, passing a {{#f}} +value will raise an exception. -Similar to {{[nonnull-] c-string}}, but if used as a result-type, the pointer -returned by the foreign code will be freed (using the C-libraries {{free(1)}}) -after copying. This type specifier is not valid as a result type for callbacks -defined with {{define-external}}. +<type>u8vector</type><br> +<type>u16vector</type><br> +<type>u32vector</type><br> +<type>s8vector</type><br> +<type>s16vector</type><br> +<type>s32vector</type><br> +<type>f32vector</type><br> +<type>f64vector</type><br> +<type>nonnull-u8vector </type><br> +<type>nonnull-u16vector </type><br> +<type>nonnull-u32vector </type><br> +<type>nonnull-s8vector </type><br> +<type>nonnull-s16vector</type><br> +<type>nonnull-s32vector</type><br> +<type>nonnull-f32vector</type><br> +<type>nonnull-f64vector</type><br> -=== [nonnull-] unsigned-c-string[*] +A [[Unit srfi-4|SRFI-4]] number-vector object, passed as a pointer to its contents. +These are allowed only as argument types, not as return types. -Same as {{c-string}}, but maps to the {{unsigned char *}} C type. +The value {{#f}} is also allowed and is passed to C as a NULL pointer. +For the {{nonnull-}} variants, passing {{#f}} will raise an exception. -=== c-string-list +=== Pointers -Expects a pointer to a list of C strings teminated by a {{NULL}} pointer and -returns a list of strings. +<type>c-pointer</type><br> +<type>(c-pointer TYPE)</type><br> +<type>nonnull-c-pointer</type><br> +<type>(nonnull-c-pointer TYPE)</type><br> -Only valid as a result type of non-callback functions. +An operating-system pointer or a locative. {{c-pointer}} is untyped, whereas +{{(c-pointer TYPE)}} points to an object of foreign type TYPE. -=== c-string-list* +The value {{#f}} is allowed and is passed to C as a {{NULL}} pointer; +similarly, NULL is returned as {{#f}}. For the two {{nonnull-}} variants, +passing {{#f}} will raise an exception, and returning NULL will result in +a null {{pointer}} object. -Similar to {{c-string-list}} but releases the storage of each string and -the pointer array using {{free(1)}}. +(Note: It is still possible to deliberately pass a null pointer through a +{{nonnull-c-pointer}} by manually creating a null pointer object, +e.g. via {{(address->pointer 0)}}.) -=== void +<type>pointer-vector</type><br> +<type>nonnull-pointer-vector</type> -Specifies an undefined return value. +A vector of foreign pointer objects; see [[Unit lolevel#Pointer vectors|Pointer vectors]]. +Permitted only as an argument type, not as return type. This type was introduced in Chicken 4.6.3. -Not allowed as argument type. +A pointer vector contains a C array of void pointers, and the argument +is passed as a {{void **}} pointer to these contents. Just as for +bytevector types, you must somehow communicate the length of this array +to the callee; there is no sentinel node or NULL terminator. -=== (const TYPE) +{{#f}} is allowed and passed as a {{NULL}} pointer. For the +{{nonnull-}} variant, passing a {{#f}} value will raise an exception. -The foreign type {{TYPE}} with an additional {{const}} specifier. +<type>(ref TYPE)</type> -=== (enum NAME) +A C++ reference type. Reference types are handled the same way as pointers +inside Scheme code. -An enumeration type. Handled internally as an {{integer}}. +<type>(function RESULTTYPE (ARGUMENTTYPE1 ... [...]) [CALLCONV])</type> -=== (c-pointer TYPE) +A function pointer. {{CALLCONV}} specifies an optional calling convention and +should be a string. The meaning of this string is entirely platform dependent. +The value {{#f}} is also allowed and is passed as a {{NULL}} pointer. -An operating-system pointer or a locative to an object of {{TYPE}}. +=== Scheme objects -=== (nonnull-c-pointer TYPE) +<type>scheme-object</type> -As {{(c-pointer TYPE)}}, but guaranteed not to be {{#f/NULL}}. +An arbitrary, raw Scheme data object (immediate or non-immediate). A +{{scheme-object}} is passed or returned as a {{C_word}}, the +internal Chicken type for objects. Typically, this consists of an +object header and tag bits. It is up to you to build or take apart +such objects using the core library routines in {{chicken.h}} and +{{runtime.c}}. -=== (ref TYPE) +More information on object structure can be found in [[Data representation]]. -A C++ reference type. Reference types are handled the same way as pointers -inside Scheme code. +<type>scheme-pointer</type><br> +<type>nonnull-scheme-pointer</type> -=== (struct NAME) +An untyped pointer to the ''contents'' of a non-immediate Scheme +object; for example, the raw byte contents of a string. Only allowed +as an argument type, not a return type. -A struct of the name {{NAME}}, which should be a string. +The value {{#f}} is also allowed and is passed as a {{NULL}} pointer. +For the {{nonnull-}} variant, passing {{#f}} will raise an exception. -Structs cannot be directly passed as arguments to foreign function, neither -can they be result values. Pointers to structs are allowed, though. +Don't confuse this type with {{(c-pointer ...)}} which means something +different (a machine-pointer object). -=== (template TYPE ARGTYPE ...) +{{scheme-pointer}} is typically used to get a pointer to the raw byte +content of strings and blobs. But if you pass in a SRFI-4 vector, you +will get a pointer to a blob object header (''not'' the blob's contents), +which is almost certainly wrong. Instead, convert to a blob +beforehand, or use a SRFI-4 specific type. -A C++ template type. For example {{vector<int>}} would be specified as -{{(template "vector" int)}}. +=== User-defined C types -Template types cannot be directly passed as arguments or returned as results. +<type>(struct NAME)</type> + +A struct of the name {{NAME}}, which should be a string. -=== (union NAME) +Structs cannot be directly passed as arguments to foreign functions, nor +can they be result values. However, pointers to structs are allowed. + +<type>(union NAME)</type> A union of the name {{NAME}}, which should be a string. -Unions cannot be directly passed as arguments to foreign function, neither can -they be result values. Pointers to unions are allowed, though. +Unions cannot be directly passed as arguments to foreign functions, nor can +they be result values. However, pointers to unions are allowed. + +<type>(enum NAME)</type> + +An enumeration type. Handled internally as an {{integer}}. -=== (instance CNAME SCHEMECLASS) +=== C++ types + +<type>(instance CNAME SCHEMECLASS)</type> A pointer to a C++ class instance wrapped into a Scheme object instance. {{CNAME}} should designate the name of the C++ class, and @@ -229,92 +325,67 @@ following operations: (make SCHEMECLASS 'this POINTER) (slot-ref INSTANCE 'this) -=== (instance-ref CNAME SCHEMECLASS) +<type>(instance-ref CNAME SCHEMECLASS)</type> A reference to a C++ class instance. -=== (function RESULTTYPE (ARGUMENTTYPE1 ... [...]) [CALLCONV]) +<type>(template TYPE ARGTYPE ...)</type> -A function pointer. {{CALLCONV}} specifies an optional calling convention and -should be a string. The meaning of this string is entirely platform dependent. -The value {{#f}} is also allowed and is passed as a {{NULL}} pointer. +A C++ template type. For example {{vector<int>}} would be specified as +{{(template "vector" int)}}. + +Template types cannot be directly passed as arguments or returned as results. +However, pointers to template types are allowed. + +=== Type qualifiers + +<type>(const TYPE)</type> -=== Mappings +The foreign type {{TYPE}} with an additional {{const}} qualifier. -Foreign types are mapped to C types in the following manner: +=== Map of foreign types to C types <table> -<tr><td>bool</td><td> -int -</td></tr><tr><td>[unsigned-]char</td><td> -[unsigned] char -</td></tr><tr><td>[unsigned-]byte</td><td> -[unsigned] char -</td></tr><tr><td>[unsigned-]short</td><td> -[unsigned] short -</td></tr><tr><td>[unsigned-]int</td><td> -[unsigned] int -</td></tr><tr><td>[unsigned-]integer</td><td> -[unsigned] int -</td></tr><tr><td>[unsigned-]long</td><td> -[unsigned] long -</td></tr><tr><td>float</td><td> -float -</td></tr><tr><td>double</td><td> -double -</td></tr><tr><td>number</td><td> -double -</td></tr><tr><td>[nonnull-]c-pointer</td><td> -void * -</td></tr><tr><td>[nonnull-]pointer-vector</td><td> -void ** -</td></tr><tr><td>[nonnull-]blob</td><td> -unsigned char * -</td></tr><tr><td>[nonnull-]u8vector</td><td> -unsigned char * -</td></tr><tr><td>[nonnull-]s8vector</td><td> -char * -</td></tr><tr><td>[nonnull-]u16vector</td><td> -unsigned short * -</td></tr><tr><td>[nonnull-]s16vector</td><td> -short * -</td></tr><tr><td>[nonnull-]u32vector</td><td> -uint32_t * -</td></tr><tr><td>[nonnull-]s32vector</td><td> -int32_t * -</td></tr><tr><td>[nonnull-]f32vector</td><td> -float * -</td></tr><tr><td>[nonnull-]f64vector</td><td> -double * -</td></tr><tr><td>[nonnull-]c-string</td><td> -char * -</td></tr><tr><td>[nonnull-]unsigned-c-string</td><td> -unsigned char * -</td></tr> -<tr><td>c-string-list</td><td>char **</td></tr> -<tr><td>symbol</td><td> -char * -</td></tr><tr><td>void</td><td> -void -</td></tr><tr><td>([nonnull-]c-pointer TYPE)</td><td> -TYPE * -</td></tr><tr><td>(enum NAME)</td><td> -enum NAME -</td></tr><tr><td>(struct NAME)</td><td> -struct NAME -</td></tr><tr><td>(ref TYPE)</td><td> -TYPE & -</td></tr><tr><td>(template T1 T2 ...)</td><td> -T1<T2, ...> -</td></tr><tr><td>(union NAME)</td><td> -union NAME -</td></tr><tr><td>(function RTYPE (ATYPE ...) [CALLCONV])</td><td> -[CALLCONV] RTYPE (*)(ATYPE, ...) -</td></tr><tr><td>(instance CNAME SNAME)</td><td> -CNAME * -</td></tr><tr><td>(instance-ref CNAME SNAME)</td><td> -CNAME & -</td></tr></table> +<tr><th>Foreign type</th><th>C type</th></tr> +<tr><td>{{bool}}</td><td>{{int}}</td></tr> +<tr><td>{{[unsigned-]char}}</td><td>{{[unsigned] char}}</td></tr> +<tr><td>{{[unsigned-]byte}}</td><td>{{[unsigned] char}}</td></tr> +<tr><td>{{[unsigned-]short}}</td><td>{{[unsigned] short}}</td></tr> +<tr><td>{{[unsigned-]int}}</td><td>{{[unsigned] int}}</td></tr> +<tr><td>{{[unsigned-]int32}}</td><td>{{[unsigned] int32_t}}</td></tr> +<tr><td>{{[unsigned-]integer}}</td><td>{{[unsigned] int}}</td></tr> +<tr><td>{{[unsigned-]integer32}}</td><td>{{[unsigned] int32_t}}</td></tr> +<tr><td>{{[unsigned-]integer64}}</td><td>{{[unsigned] int64_t}}</td></tr> +<tr><td>{{[unsigned-]long}}</td><td>{{[unsigned] long}}</td></tr> +<tr><td>{{float}}</td><td>{{float}}</td></tr> +<tr><td>{{double}}</td><td>{{double}}</td></tr> +<tr><td>{{number}}</td><td>{{double}}</td></tr> +<tr><td>{{[nonnull-]c-pointer}}</td><td>{{void *}}</td></tr> +<tr><td>{{[nonnull-]pointer-vector}}</td><td>{{void **}}</td></tr> +<tr><td>{{[nonnull-]blob}}</td><td>{{unsigned char *}}</td></tr> +<tr><td>{{[nonnull-]u8vector}}</td><td>{{unsigned char *}}</td></tr> +<tr><td>{{[nonnull-]s8vector}}</td><td>{{char *}}</td></tr> +<tr><td>{{[nonnull-]u16vector}}</td><td>{{unsigned short *}}</td></tr> +<tr><td>{{[nonnull-]s16vector}}</td><td>{{short *}}</td></tr> +<tr><td>{{[nonnull-]u32vector}}</td><td>{{uint32_t *}}</td></tr> +<tr><td>{{[nonnull-]s32vector}}</td><td>{{int32_t *}}</td></tr> +<tr><td>{{[nonnull-]f32vector}}</td><td>{{float *}}</td></tr> +<tr><td>{{[nonnull-]f64vector}}</td><td>{{double *}}</td></tr> +<tr><td>{{[nonnull-]c-string}}</td><td>{{char *}}</td></tr> +<tr><td>{{[nonnull-]unsigned-c-string}}</td><td>{{unsigned char *}}</td></tr> +<tr><td>{{c-string-list}}</td><td>{{char **}}</td></tr> +<tr><td>{{symbol}}</td><td>{{char *}}</td></tr> +<tr><td>{{void}}</td><td>{{void}}</td></tr> +<tr><td>{{([nonnull-]c-pointer TYPE)}}</td><td>{{TYPE *}}</td></tr> +<tr><td>{{(enum NAME)}}</td><td>{{enum NAME}}</td></tr> +<tr><td>{{(struct NAME)}}</td><td>{{struct NAME}}</td></tr> +<tr><td>{{(ref TYPE)}}</td><td>{{TYPE &}}</td></tr> +<tr><td>{{(template T1 T2 ...)}}</td><td>{{T1<T2, ...>}}</td></tr> +<tr><td>{{(union NAME)}}</td><td>{{union NAME}}</td></tr> +<tr><td>{{(function RTYPE (ATYPE ...) [CALLCONV])}}</td><td>{{[CALLCONV] RTYPE (*)(ATYPE, ...)}}</td></tr> +<tr><td>{{(instance CNAME SNAME)}}</td><td>{{CNAME *}}</td></tr> +<tr><td>{{(instance-ref CNAME SNAME)}}</td><td>{{CNAME &}}</td></tr> +</table> --- Previous: [[Accessing external objects]]Trap