Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
== Outdated egg! This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for [[/eggref/5/foreigners|the CHICKEN 5 version of this egg]], if it exists. If it does not exist, there may be equivalent functionality provided by another egg; have a look at the [[https://wiki.call-cc.org/chicken-projects/egg-index-5.html|egg index]]. Otherwise, please consider porting this egg to the current version of CHICKEN. == foreigners [[toc:]] === Synopsis '''foreigners''' is a collection of useful FFI macros. To use this extension, import both the core FFI syntax and the syntax we provide: (import foreign) ; core FFI syntax (import foreigners) ; this egg === Interface ==== define-foreign-record-type <macro>(define-foreign-record-type name [decl ...] slot ...)</macro> This macro defines accessor procedures for a C structure definition. It is the counterpart to Chicken 3's {{define-foreign-record}}, but modeled after SRFI 9's {{define-record-type}} for better hygiene. {{NAME}} should either be a symbol or a list of the form {{(TYPENAME FOREIGNNAME)}}. If {{NAME}} is a symbol, then a C declaration will be generated that defines a C struct named {{struct NAME}}. If {{NAME}} is a list, then no struct declaration will be generated and {{FOREIGNNAME}} should name an existing C record type. A foreign-type specifier named {{NAME}} (or {{TYPENAME}}) will be defined as a pointer to the given C structure. ===== Slot definitions A {{SLOT}} definition should be a list of one of the following forms: (type slotname getter [setter]) (type (slotname size) getter [setter]) where {{TYPE}}, {{SLOTNAME}}, {{GETTER}} and {{SETTER}} are all symbols. The latter form defines an array of {{SIZE}} elements of the type {{TYPE}} embedded in the structure. For every slot, a getter procedure and optionally a setter procedure will be generated. ===== The getter (getter foreign-record-pointer [index]) A procedure of one argument (a pointer to a C structure), that returns the slot value of the slot {{SLOTNAME}}. If a {{SIZE}} has been given in the slot definition, then an additional argument {{INDEX}} is required that specifies the index of an array-element. ===== The setter (setter foreign-record-pointer [index] value) A procedure of two arguments (a pointer to a C structure) and a value, that sets the slot value of the slot {{SLOTNAME}} in the structure. If a {{SIZE}} has been given in the slot definition, then an additional argument {{INDEX}} is required for the array index. If the setter is omitted from the slot form, no setter procedure will be generated. This is the equivalent of the {{(const ...)}} modifier in Chicken 3. Slots of the types {{(struct ...)}} or {{(union ...)}} are accessed as pointers to the embedded struct (or union) and no setter will be generated regardless. ===== record declarations Additionally, special record declarations ({{DECL ...}}) may be given, where each declaration consists of a list of the form {{(KEYWORD ARGUMENT ...)}}. Declarations ''must'' occur before slots. The available declarations are: ====== constructor (constructor: NAME) Generate a constructor-procedure with no arguments that has the name {{NAME}} (a symbol) that returns a pointer to a structure of this type. The storage will be allocated with {{malloc(3)}}. Memory allocated by a constructor is ''not'' automatically freed. You will probably need to generate a destructor (see below) and call it manually, or register a finalizer yourself. ====== destructor (destructor: NAME) Generate a destructor function with the name {{NAME}} that takes a pointer to a structure of this type as its single argument and releases the storage with {{free(3)}}. If the argument is {{#f}}, the destructor procedure does nothing. ==== define-foreign-enum-type <macro>(define-foreign-enum-type (type-name native-type [default-value]) (scheme->number number->scheme) enumspec ...)</macro> Defines a foreign-type that maps the elements of a C/C++ enum (or a enum-like list of constants) to and from a set of symbols. Also defines a pair of conversion procedures which can be used to do this mapping manually, along with a foreign-variable for each enumeration value. * {{type-name}} is the foreign type name; * {{native-type}} is the underlying type, e.g. {{int}} or {{(enum "foo")}}; * {{default-value}} is the result of mapping from the native type when no such mapping exists. When supplied the form is used unquoted, otherwise the result is '(); * {{scheme->number}} is the name of a procedure which will convert a symbol (or list of symbols) into the corresponding numeric enum value; * {{number->scheme}} is a procedure converting an enum into a symbol; * {{enumspec}} is a specification for each enum value, described in detail below. The two procedures are defined by the macro in lexical scope for your use, and are also used in the foreign-type conversion: (define-foreign-type type-name native-type scheme->number number->scheme) If passed a list of symbols, {{scheme->number}} will combine their numeric values with {{bitwise-ior}}. However, {{number->scheme}} returns a single symbol and will not decompose a value into its component symbols; rather, you will probably get {{default-value}}. ===== enumspec The most general form of {{enumspec}} is {{((symbol var-name) native-name destination-value)}}. Some of these items can be omitted; see below. For each of these forms, a foreign-variable is generated: (define-foreign-variable var-name native-type native-name) Furthermore, forward and reverse mappings are added: {{scheme->number}}: from {{symbol}} to the foreign value {{native-name}}; also accepts {{symbol}}'s keyword equivalent {{number->scheme}}: from {{native-name}} to {{destination-value}} Normally, {{destination-value}} is omitted from the spec, and the {{symbol}} is used as the destination value, making the mapping reversible. But occasionally, overriding the value can be useful, for example in changing a zero return value to #f. If {{native-name}} is omitted, {{symbol}} is used --- useful if you want your Scheme symbols to reflect the underlying constant names. If {{var-name}} is omitted, a temporary generated symbol is used, so the foreign-variable will not be visible to your compilation unit. Stating the {{enumspec}} rules explicitly: ((s v) n d) ; general form ((s v) n) -> ((s v) n s) ((s) n d) -> ((s t) n d) ; t is a temporary name (gensym) ((s) n) -> ((s t) n s) (s n d) -> ((s s) n d) (s n) -> ((s s) n s) s -> ((s s) s s) === Examples ==== define-foreign-enum-type Example of a module which uses {{define-foreign-enum-type}}: #> #define STATUS_OK 0 #define STATUS_BUSY 1 #define STATUS_FAIL 2 static int _status = STATUS_OK; int get_status() { return _status; } void set_status(int s) { _status = s; } <# (module enum-1 (status->int int->status get-status set-status busy?) (import scheme chicken foreigners) (define-foreign-enum-type (status int) (status->int int->status) ((ok status/ok) STATUS_OK) ((busy status/busy) STATUS_BUSY) ((fail status/fail) STATUS_FAIL)) (define get-status (foreign-lambda status "get_status")) (define set-status (foreign-lambda void "set_status" status)) (define (busy? s) (= s status/busy)) ) This may be tested with: (require-extension test) (require-extension enum-1) (test "status->int" 1 (status->int 'busy)) (test "int->status" 'fail (int->status 2)) (set-status 'busy) (test "get-status" 'busy (get-status)) (test "status/busy via busy?" #t (busy? (status->int (get-status)))) ==== define-foreign-record-type Example that wraps the {{servent}} structure --- see {{getservent(3)}}. #> struct servent { char *s_name; char **s_aliases; int s_port; char *s_proto; }; <# (define-foreign-type port-number int ; used by servent type (foreign-lambda int "htons" int) (foreign-lambda int "ntohs" int) ) (define-foreign-record-type (servent "struct servent") (constructor: make-servent) (destructor: free-servent) (c-string s_name servent-name servent-name-set!) (c-pointer s_aliases servent-s_aliases) ; const (port-number s_port servent-port servent-port-set!) (c-string s_proto servent-proto servent-proto-set!)) === Author Jim Ursetto === Version history * 1.1 define-foreign-enum-type bugfix * 1.0 Initial release === License BSD.
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you add 3 to 10?