((section 2 "Outdated egg!" (p "This is an egg for CHICKEN 4, the unsupported old release.  You're almost certainly looking for " (int-link "/eggref/5/easyffi" "the CHICKEN 5 version of this egg") ", if it exists.") (p "If it does not exist, there may be equivalent functionality provided by another egg; have a look at the " (link "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.") (tags "egg" "ffi") (toc)) (section 2 "The \"Easy\" Foreign Function Interface" (p (i "Note: see " (int-link "/eggref/4/bind" "bind") " for a newer version of this extension that provides a simplified interface and better " (int-link "/eggref/4/coops" "coops") " integration.")) (p "This extension provides a parser for a restricted subset of C and C++ that allows the easy generation of foreign variable declarations, procedure bindings and C++ class wrappers. The parser is invoked via the " (tt "foreign-parse") " form, which extracts binding information and generates the necessary code. An example:") (highlight scheme "(foreign-declare \"\n#include <math.h>\n\")\n\n(foreign-parse \"extern double sin(double);\")\n\n(print (sin 3.14))") (p "The parser would generate code that is equivalent to") (pre "(foreign-declare \"\n#include <math.h>\n\")") (pre "(define sin (foreign-lambda double \"sin\" double))") (p "Note that the read syntax " (tt "#>[SPEC] ... <#") " provides a somewhat simpler way of using the parser. The example above could alternatively be expressed as") (pre "#>!\nextern double sin(double);\n<#") (pre "(print (sin 3.14))") (p "Another example, here using C++. Consider the following class:") (pre "// file: foo.h\n\nclass Foo {\n private:\n  int x_;\n public:\n  Foo(int x);\n  void setX(int x);\n  int getX();\n};") (p "To generate a wrapper class that provides generic functions for the constructor and the " (tt "setX") " and " (tt "getX") " methods, we can use the following class definition:") (pre "; file: test-foo.scm") (pre "(require-extension tinyclos)\n\n#>!\n#include \"Foo.h\"\n<#\n\n(define x (make <Foo> 99))\n(print (getX x))              ; prints ''99''\n(setX x 42)\n(print (getX x))              ; prints ''42''\n(destroy x)") (p "Provided the file " (tt "foo.o") " contains the implementation of the class " (tt "Foo") ", the given example could be compiled like this (assuming a UNIX like environment):") (pre "% csc -X easyffi test-foo.scm foo.o -c++") (p "To use the C++ interface, the " (int-link "tinyclos") " extension is needed.") (p "Here is another example, a minimal " (i "Hello world") " application for QT. We can see the three different ways of embedding C/C++ code in Scheme:") (pre "; compile like this: \n; csc -X easyffi hello.scm -c++ -C -IQTDIR/include -L \"-LQTDIR/lib -lqt\"\n\n(require-extension tinyclos)") (pre "; Include into generated code, but don't parse:\n#>\n#include <qapplication.h>\n#include <qpushbutton.h>\n<#") (pre "; Parse but don't embed: we only want wrappers for a few classes:\n#>?\nclass QWidget \n{\npublic:\n  void resize(int, int);\n  void show();\n};") (pre "class QApplication \n{\npublic:\n  QApplication(int, char **);\n  ~QApplication();\n  void setMainWidget(QWidget *);\n  void exec();\n};") (pre "class QPushButton : public QWidget\n{\npublic:\n  QPushButton(char *, QWidget *);\n  ~QPushButton();\n}\n<#") (pre "(define a (apply make <QApplication> (receive (argc+argv))))\n(define hello (make <QPushButton> \"hello world!\" #f))\n(resize hello 100 30)\n(setMainWidget a hello)\n(show hello)\n(exec a)\n(destroy hello)\n(destroy a)") (section 3 "Usage" (p "To use this facility, you can either run it in the interpreter and generate files with wrapper code and interact using an API, or you can load it as a compiler extension. To do the latter, pass " (tt "-X easyffi") " to " (tt "csc") " (or " (tt "-extend easyffi") " to " (tt "chicken") "). " (tt "-R easyffi") " works also, but will not make the special read-syntax available.") (p "This extension defines the " (tt "easyffi") " module.") (p "To see the expanded code generated during compilation, compile with " (tt "-debug F") ".") (p "A command-line tool named " (tt "chicken-wrap") " is also available that translates C source or header files into Scheme code. Enter") (pre " % chicken-wrap -help") (p "for more information.") (p "The API provides the following procedures:") (section 4 "parse-easy-ffi" (def (sig (procedure "(parse-easy-ffi STRING)" (id parse-easy-ffi))) (p "Parses the C/C++ code in STRING and returns a list of top-level expressions representing compilable bindings to the defintions contained."))) (section 4 "register-ffi-macro" (def (sig (procedure "(register-ffi-macro STRING)" (id register-ffi-macro))) (p "Defines a preprocessor macro named STRING for allowing conditional processing using " (tt "#ifdef ... #endif") "."))) (section 4 "check-c-syntax" (def (sig (procedure "(check-c-syntax STRING)" (id check-c-syntax))) (p "Perform a superficial C/C++ syntax check and signal an error if any lexical or syntactic errors are detected."))) (section 4 "foreign-parse" (def (sig (syntax "(foreign-parse STRING ...)" (id foreign-parse))) (p "Parse given strings and generate foreign-interface bindings."))) (section 4 "foreign-parse/declare" (def (sig (syntax "(foreign-parse/declare STRING ...)" (id foreign-parse/declare))) (pre "") (p "Parse and include strings into the generated code."))) (section 4 "foreign-include-path" (def (sig (syntax "(foreign-include-path STRING ...)" (id foreign-include-path))) (p "Appends the paths given in " (tt "STRING ...") " to the list of available include paths to be searched when an " (tt "#include ...") " form is processed by " (tt "foreign-parse") ".")))) (section 3 "#> ... <# Syntax" (p "Occurrences of the special read syntax " (tt "#>[SPEC ...] ...<#") " will be handled according to " (tt "SPEC") ":") (ul (li "If " (tt "SPEC") " is the " (tt "?") " character, the text following up to the next " (tt "<#") " will be processed as a " (tt "(declare (foreign-parse \"...\"))") " declaration (the code will be processed by the FFI parser described in this section).") (li "If " (tt "SPEC") " is the " (tt "!") " character, the text will be embedded as " (tt "(foreign-parse/declare \"...\")") ". It will be both included verbatim in the declaration section of the generated C/C++ file and processed by the FFI parser.") (li "If " (tt "SPEC") " is the " (tt ":") " character, the text will be so it will be executed at the location where it appears.") (li "If " (tt "SPEC") " is a list of the form " (tt "(TAG ...)") ", then each " (tt "TAG") " (which should be a symbol) specifies what should be done with the text: ")) (pre " declare   (foreign-declare \"...\")\n parse     (foreign-parse \"...\")\n execute   (foreign-code \"...\")") (ul (li "If any other character follows the " (tt "#>") ", then the complete text will be included verbatim in the declaration part of the generated file (as in a " (tt "foreign-declare") " form). "))) (section 3 "General operation" (p "The parser will generally perform the following functions") (ul (li "Translate macro, enum-definitions and constants into " (tt "define-foreign-variable") " or " (tt "define-constant") " forms") (li "Translate function prototypes into " (tt "foreign-lambda") " forms") (li "Translate variable declarations into accessor procedures") (li "Handle basic preprocessor operations") (li "Translate simple C++ class definitions into TinyCLOS wrapper classes and methods")) (p "Basic token-substitution of macros defined via " (tt "#define") " is performed. The preprocessor commands " (tt "#ifdef") ", " (tt "#ifndef") ", " (tt "#else") ", " (tt "#endif") ", " (tt "#undef") " and " (tt "#error") " are handled. The preprocessor commands " (tt "#if") " and " (tt "#elif") " are not supported and will signal an error when encountered by the parser, because C expressions (even if constant) are not parsed. The preprocessor command " (tt "#pragma") " is allowed but will be ignored.") (p "During processing of " (tt "foreign-parse") " declarations the macro " (tt "CHICKEN") " is defined (similar to the C compiler option " (tt "-DCHICKEN") ").") (p "Macro- and type-definitions are available in subsequent " (tt "foreign-parse") " declarations. C variables declared generate a procedure with zero or one argument with the same name as the variable. When called with no arguments, the procedure returns the current value of the variable. When called with an argument, then the variable is set to the value of that argument. C and C++ style comments are supported. Variables declared as " (tt "const") " will generate normal Scheme variables, bound to the initial value of the variable.") (p "Function-, member-function and constructor/destructor definitions may be preceded by the " (tt "___safe") " qualifier, which marks the function as (possibly) performing a callback into Scheme. If a wrapped function calls back into Scheme code, and " (tt "___safe") " has not been given very strange and hard to debug problems will occur.") (p "Functions and member functions prefixed with " (tt "___discard") " and a result type that maps to a Scheme string (" (tt "c-string") "), will have their result type changed to " (tt "c-string*") " instead.") (p "Constants (as declared by " (tt "#define") " or " (tt "enum") ") are not visible outside of the current Compilation units unless the " (tt "export_constants") " pseudo declaration has been used. Only numeric or character constants are directly supported.") (p "Function-arguments may be preceded by " (tt "___in") ", " (tt "___out") " and " (tt "___inout") " qualifiers to specify values that are passed by reference to a function, or returned by reference. Only basic types (booleans, numbers and characters) can be passed using this method. During the call a pointer to a temporary piece of storage containing the initial value (or a random value, for " (tt "___out") " parameters) will be allocated and passed to the wrapped function. This piece of storage is subject to garbage collection and will move, should a callback into Scheme occur that triggers a garbage collection. Multiple " (tt "__out") " and " (tt "___inout") " parameters will be returned as multiple values, preceded by the normal return value of thhe function (if not " (tt "void") "). Here is a simple example:") (pre "#>!\n#ifndef CHICKEN\n#include <math.h>\n#endif") (pre "double modf(double x, ___out double *iptr);\n<#") (pre "(let-values ([(frac int) (modf 33.44)])\n  ...)") (p "Function-arguments may be preceded by " (tt "___length(ID)") ", where " (tt "ID") " designates the name of another argument that must refer to a number vector or string argument. The value of the former argument will be computed at run-time and thus can be omitted:") (pre "#>!\n(require-extension srfi-4)") (pre "double sumarray(double *arr, ___length(arr) int len)\n{\n  double sum = 0;") (pre "  while(len--) sum += *(arr++);") (pre "  return sum;\n}\n<#") (pre "(print (sumarray (f64vector 33 44 55.66)))") (p "The length variable may be positioned anywhere in the argument list. Length markers may only be specified for arguments passed as SRFI-4 byte-vectors, byte-vectors (as provided by the " (tt "lolevel") " library unit) or strings.") (p "Structure and union definitions containing actual field declarations generate getter procedures (and SRFI-17 setters when declared " (tt "___mutable") " or the " (tt "mutable_fields") " pseudo declaration has been used) The names of these procedures are computed by concatenating the struct (or union) name, a hyphen (" (tt "\"-\"") ") and the field name. Structure definitions with fields may not be used in positions where a type specifier is normally expected. The field accessors operate on struct/union pointers only. Additionally a zero-argument procedure named " (tt "make-<structname>") " will be generated that allocates enough storage to hold an instance of the structure (or union). Prefixing the definition with " (tt "___abstract") " will omit the creation procedure.") (pre "#>!\nstruct My_struct { int x; ___mutable float y; };") (pre "typedef struct My_struct My_struct;") (pre "My_struct *make_struct(int x, float y) \n{\n  My_struct *s = (My_struct *)malloc(sizeof(My_struct));\n  s->x = x;\n  s->y = y;\n  return s;\n}\n<#") (p "will generate the following definitions:") (pre "(make-My_struct) -> PTR\n(My_struct-x PTR) -> INT\n(My_struct-y PTR) -> FLOAT\n(set! (My_struct-y PTR) FLOAT)\n(make_struct INT FLOAT) -> PTR") (p "Nested structs or unions are not supported (but pointers to nested structs/unions are).") (p "All specially handled tokens preceded with " (tt "___") " are defined as C macros in the headerfile " (tt "chicken.h") " and will usually expand into nothing, so they don't invalidate the processed source code.") (p "C++ " (tt "namespace") " declarations of the form " (tt "namespace NAME @{ ... @") "} recognized but will be completely ignored.") (p "Keep in mind that this is not a fully general C/C++ parser. Taking an arbitrary headerfile and feeding it to CHICKEN will in most cases not work or generate riduculuous amounts of code. This FFI facility is for carefully written headerfiles, and for declarations directly embedded into Scheme code.")) (section 3 "Pseudo declarations" (p "Using the " (tt "___declare(DECL, VALUE)") " form, pseudo declarations can be embedded into processed C/C++ code to provide additional control over the wrapper generation. Pseudo declarations will be ignored when processed by the system's C/C++ compiler.") (pre "abstract [values: <string>]") (p "Marks the C++ class given in " (tt "<string>") " as being abstract, i.e. no constructor will be defined. Alternatively, a class definition may be prefixed with " (tt "___abstract") ".") (pre "class_finalizers [values: yes, no]") (p "Automatically generates calls to " (tt "set-finalizer!") " so that any unused references to instances of subsequently defined C++ class wrappers will be destroyed. This should be used with care: if the embedded C++ object which is represented by the reclaimed TinyCLOS instance is still in use in foreign code, then unpredictable things will happen.") (pre "mutable_fields [values: yes, no]") (p "Specifies that all struct or union fields should generate setter procedures (the default is to generate only setter procedures for fields declared " (tt "___mutable") ").") (pre "destructor_name [values: <string>]") (p "Specifies an alternative name for destructor methods (the default is " (tt "destroy") ".") (pre "export_constants [values: yes (default), no]") (p "Define a global variable for constant-declarations (as with " (tt "#define") " or " (tt "enum") "), making the constant available outside the current compilation unit. Use the values " (tt "yes") "/" (tt "1") " for switching constant export on, or " (tt "no") "/" (tt "0") " for switching it off.") (pre "exception_handler [values: <string>]") (p "Defines C++ code to be executed when an exception is triggered inside a C++ class member function. The code should be one or more " (tt "catch") " forms that perform any actions that should be taken in case an exception is thrown by the wrapped member function:") (pre "#>!\n___declare(exception_handler, \"catch(...) { return 0; }\")") (pre "class Foo {\n public:\n  Foo *bar(bool f) { if(f) throw 123; else return this; }\n};\n<#") (pre "(define f1 (make <Foo>))\n(print (bar f1 #f))\n(print (bar f1 #t))") (p "will print " (tt "<Foo>") " and " (tt "#f") ", respectively.") (pre "full_specialization [values: yes, no]") (p "Enables " (i "full specialization") " mode. In this mode all wrappers for functions, member functions and static member functions are created as fully specialized TinyCLOS methods. This can be used to handle overloaded C++ functions properly. Only a certain set of foreign argument types can be mapped to TinyCLOS classes, as listed in the following table:") (pre "char             <char>\nbool             <bool>\nc-string         <string>\nunsigned-char    <exact>\nbyte             <exact>\nunsigned-byte    <exact>\n[unsigned-]int   <exact>\n[unsigned-]short <exact>\n[unsigned-]long  <integer>\n[unsigned-]integer     <integer>\nfloat            <inexact>\ndouble           <inexact>\nnumber           <number>\n(enum _)char     <exact>\n(const T)char    (as T)\n(function ...)   <pointer>\nc-pointer        <pointer>\n(pointer _)      <pointer>\n(c-pointer _)    <pointer>\nu8vector         <u8vector>\ns8vector         <s8vector>\nu16vector        <u16vector>\ns16vector        <s16vector>\nu32vector        <u32vector>\ns32vector        <s32vector>\nf32vector        <f32vector>\nf64vector        <f64vector>") (p "All other foreign types are specialized as " (tt "<top>") ".") (p "Full specialization can be enabled globally, or only for sections of code by enclosing it in") (pre "___declare(full_specialization, yes)\n...\nint foo(int x);\nint foo(char *x);\n...\n___declare(full_specialization, no)") (p "Alternatively, member function definitions may be prefixed by " (tt "___specialize") " for specializing only specific members.") (pre "prefix [values: <string>]") (p "Sets a prefix that should be be added to all generated Scheme identifiers. For example") (pre "___declare(prefix, \"mylib:\")\n#define SOME_CONST     42") (p "would generate the following code:") (pre "(define-constant mylib:SOME_CONST 42)") (p "To switch prefixing off, use the values " (tt "no") " or " (tt "0") ". Prefixes are not applied to Class names.") (pre "rename [value: <string>]") (p "Defines to what a certain C/C++ name should be renamed. The value for this declaration should have the form " (tt "\"<c-name>;<scheme-name>\"") ", where " (tt "<c-name>") " specifies the C/C++ identifier occurring in the parsed text and " (tt "<scheme-name>") " gives the name used in generated wrapper code.") (pre "scheme [value: <string>]") (p "Embeds the Scheme expression " (tt "<string>") " in the generated Scheme code.") (pre "substitute [value: <string>]") (p "Declares a name-substitution for all generated Scheme identifiers. The value for this declaration should be a string containing a regular expression and a replacement string (separated by the " (tt ";") " character):") (pre "___declare(substitute, \"^SDL_;sdl:\")") (pre "extern void SDL_Quit();") (p "generates") (pre "(define sdl:Quit\n  (foreign-lambda integer \"SDL_Quit\") )") (pre "transform [values: <string>]") (p "Defines an arbitrary transformation procedure for names that match a given regular expression. The value should be a string containing a regular expression and a Scheme expression that evaluates to a procedure of one argument. If the regex matches, the procedure will be called at compile time with the match-result (as returned by " (tt "string-match") ") and should return a string with the desired transformations applied:") (pre "(require-for-syntax 'srfi-13)") (pre "#>!\n___declare(transform, \"([A-Z]+)_(.*);(lambda (x) (string-append (cadr x) \\\"-\\\" (string-downcase (caddr x))))\")") (pre "void FOO_Bar(int x) { return x * 2; }\n<#") (pre "(print (FOO-bar 33))") (pre "default_renaming [value: <string>]") (p "Chooses a standard name-transformation, converting underscores (" (tt "_") ") to hyphens (" (tt "-") ") and transforming " (i "CamelCase") " into " (i "camel-case") ". All uppercase characters are also converted to lowercase. The result is prefixed with the argument string (equivalent to the " (tt "prefix") " pseudo declaration).") (pre "type [value: <string>]") (p "Declares a foreign type transformation, similar to " (tt "define-foreign-type") ". The value should be a list of two to four items, separated by the " (tt ";") " character: a C typename, a Scheme foreign type specifier and optional argument- and result-value conversion procedures.") (pre ";;;; foreign type that converts to unicode (assumes 4-byte wchar_t):\n;\n; - Note: this is rather kludgy and is only meant to demonstrate the `type'\n;         pseudo-declaration") (pre "(require-extension srfi-4)") (pre "(define mbstowcs (foreign-lambda int \"mbstowcs\" nonnull-u32vector c-string int))") (pre "(define (str->ustr str)\n  (let* ([len (string-length str)]\n         [us (make-u32vector (add1 len) 0)] )\n    (mbstowcs us str len)\n    us) )") (pre "#>!\n___declare(type, \"unicode;nonnull-u32vector;str->ustr\")") (pre "static void foo(unicode ws)\n{\n  printf(\"\\\"%ls\\\"\\n\", ws);\n}\n<#") (pre "(foo \"this is a test!\")") (pre "opaque [value: <string>]") (p "Similar to " (tt "type") ", but provides automatic argument- and result conversions to wrap a value into a structure:") (pre "#>?\n___declare(opaque, \"myfile;(pointer \\\"FILE\\\")\")") (pre "myfile fopen(char *, char *);\n<#") (pre "(fopen \"somefile\" \"r\")   ==> <myfile>") (p (tt "___declare(opaque, \"TYPENAME;TYPE\")") " is basically equivalent to " (tt "___declare(type, \"TYPENAME;TYPE;TYPE->RECORD;RECORD->TYPE\")") " where " (tt "TYPE->RECORD") " and " (tt "RECORD->TYPE") " are compiler-generated conversion functions that wrap objects of type " (tt "TYPE") " into a record and back.")) (section 3 "Grammar" (p "The parser understand the following grammar:") (pre "PROGRAM = PPCOMMAND\n        | DECLARATION \";\"\n\nPPCOMMAND = \"#define\" ID [TOKEN ...]\n          | \"#ifdef\" ID\n          | \"#ifndef\" ID\n          | \"#else\"\n          | \"#endif\"\n          | \"#undef\" ID\n          | \"#error\" TOKEN ...\n          | \"#include\" INCLUDEFILE\n          | \"#import\" INCLUDEFILE\n          | \"#pragma\" TOKEN ...\n\nDECLARATION = FUNCTION\n            | VARIABLE\n            | ENUM\n            | TYPEDEF\n            | CLASS\n            | CONSTANT\n            | STRUCT\n            | NAMESPACE\n            | \"___declare\" \"(\" PSEUDODECL \",\" <tokens> \")\"\n\nSTRUCT = (\"struct\" | \"union\") ID [\"{\" {[\"___mutable\"] TYPE {\"*\"} ID {\",\" {\"*\"} ID}} \"}]\n\nNAMESPACE = \"namespace\" ID \"{\" DECLARATION ... \"}\"\n\nINCLUDEFILE = \"\\\"\" ... \"\\\"\"\n            | \"<\" ... \">\"\n\nFUNCTION = {\"___safe\" | \"___specialize\" | \"___discard\"} [STORAGE] TYPE ID \"(\" ARGTYPE \",\" ... \")\" [CODE]\n         | {\"___safe\" | \"___specialize\" | \"___discard\"} [STORAGE] TYPE ID \"(\" \"void\" \")\" [CODE]\n\nARGTYPE = [IOQUALIFIER] TYPE [ID [\"[\" ... \"]\"]]\n\nIOQUALIFIER = \"___in\" | \"___out\" | \"___inout\" | LENQUALIFIER\n\nLENQUALIFIER = \"___length\" \"(\" ID \")\"\n\nVARIABLE = [STORAGE] ENTITY [\"=\" INITDATA]\n\nENTITY = TYPE ID [\"[\" ... \"]\"]\n\nSTORAGE = \"extern\" | \"static\" | \"volatile\" | \"inline\"\n\nCONSTANT = \"const\" TYPE ID \"=\" INITDATA\n\nPSEUDODECL = \"export_constants\"\n           | \"prefix\"\n           | \"substitute\"\n           | \"abstract\"\n           | \"type\"\n           | \"scheme\"\n           | \"rename\"\n           | \"transform\"\n           | \"full_specialization\"\n           | \"destructor_name\"\n           | \"class_finalizers\"\n           | \"exception_handler\"\n           | \"mutable_fields\"\n\nENUM = \"enum\" \"{\" ID [\"=\" (NUMBER | ID)] \",\" ... \"}\"\n\nTYPEDEF = \"typedef\" TYPE [\"*\" ...] [ID]\n\nTYPE = [\"const\"] BASICTYPE [(\"*\" ... | \"&\" | \"<\" TYPE \",\" ... \">\" | \"(\" \"*\" [ID] \")\" \"(\" TYPE \",\" ... \")\")]\n\nBASICTYPE = [\"unsigned\" | \"signed\"] \"int\" \n          | [\"unsigned\" | \"signed\"] \"char\" \n          | [\"unsigned\" | \"signed\"] \"short\" [\"int\"]\n          | [\"unsigned\" | \"signed\"] \"long\" [\"int\"]\n          | [\"unsigned\" | \"signed\"] \"___byte\" \n          | \"size_t\"\n          | \"float\"\n          | \"double\"\n          | \"void\"\n          | \"bool\"\n          | \"___bool\"\n          | \"___scheme_value\"\n          | \"___scheme_pointer\"\n          | \"___byte_vector\"\n          | \"___pointer\" TYPE \"*\"\n          | \"C_word\"\n          | \"___fixnum\"\n          | \"___number\"\n          | \"___symbol\"\n          | \"___u32\"\n          | \"___s32\"\n          | \"___s64\"\n          | \"__int64\"\n          | \"int64_t\"\n          | \"struct\" ID\n          | \"union\" ID\n          | \"enum\" ID\n          | ID\n\nCLASS = [\"___abstract\"] \"class\" ID [\":\" [QUALIFIER] ID \",\" ...] \"{\" MEMBER ... \"}\"\n\nMEMBER = [QUALIFIER \":\"] [\"virtual\"] (MEMBERVARIABLE | CONSTRUCTOR | DESTRUCTOR | MEMBERFUNCTION)\n\nMEMBERVARIABLE = TYPE ID [\"=\" INITDATA]\n\nMEMBERFUNCTION = {\"___safe\" | \"static\" | \"___specialize\" | \"___discard\"} TYPE ID \"(\" ARGTYPE \",\" ... \")\" [\"const\"] [\"=\" \"0\"] [CODE]\n               | {\"___safe\" | \"static\" | \"___specialize\" | \"___discard\"} TYPE ID \"(\" \"void\" \")\" [\"const\"] [\"=\" \"0\"] [CODE]\n\nCONSTRUCTOR = [\"___safe\"] [\"explicit\"] ID \"(\" ARGTYPE \",\" ... \")\" [BASECONSTRUCTORS] [CODE]\n\nDESTRUCTOR = [\"___safe\"] \"~\" ID \"(\" [\"void\"] \")\" [CODE]\n\nQUALIFIER = (\"public\" | \"private\" | \"protected\")\n\nNUMBER = <a C integer or floating-point number, in decimal, octal or hexadecimal notation>\n\nINITDATA = <everything up to end of chunk>\n\nBASECONSTRUCTORS = <everything up to end of chunk>\n\nCODE = <everything up to end of chunk>") (p "The following table shows how argument-types are translated:") (pre "[unsigned] char          char\n[unsigned] short         [unsigned-]short\n[unsigned] int           [unsigned-]integer\n[unsigned] long          [unsigned-]long\n___u32                   unsigned-integer32\n___s32                   integer32\n___s64                   integer64\nint64_t                  integer64\n__int64                  integer64\nfloat                    float\ndouble                   double\nsize_t                   unsigned-integer\nbool                     int\n___bool                  int\n___fixnum                int\n___number                number\n___symbol                symbol\n___scheme_value          scheme-object\nC_word                   scheme-object\n___scheme_pointer        scheme-pointer\nchar *                   c-string\nsigned char *            s8vector\n[signed] short *         s16vector\n[signed] int *           s32vector\n[signed] long *          s32vector\nunsigned char *          u8vector\nunsigned short *         u16vector\nunsigned int *           u32vector\nunsigned long *          u32vector\nfloat *                  f32vector\ndouble *                 f64vector\n___byte_vector           byte-vector\nCLASS *                  (instance CLASS <CLASS>)\nCLASS &                  (instance-ref CLASS <CLASS>)\nTYPE *                   (pointer TYPE)\nTYPE &                   (ref TYPE)\nTYPE<T1, ...>            (template TYPE T1 ...)\nTYPE1 (*)(TYPE2, ...)    (function TYPE1 (TYPE2 ...))") (p "The following table shows how result-types are translated:") (pre "void                     void\n[unsigned] char          char\n[unsigned] short         [unsigned-]short\n[unsigned] int           [unsigned-]integer\n[unsigned] long          [unsigned-]long\n___u32                   unsigned-integer32\n___s32                   integer32\n___s64                   integer64\nint64_t                  integer64\n__int64                  integer64\nfloat                    float\ndouble                   double\nsize_t                   unsigned-integer\nbool                     bool\n___bool                  bool\n___fixnum                int\n___number                number\n___symbol                symbol\n___scheme_value          scheme-object\nchar *                   c-string\nTYPE *                   (pointer TYPE)\nTYPE &                   (ref TYPE)\nTYPE<T1, ...>            (template TYPE T1 ...)\nTYPE1 (*)(TYPE2, ...)    (function TYPE1 (TYPE2 ...))\nCLASS *                  (instance CLASS <CLASS>)\nCLASS &                  (instance-ref CLASS <CLASS>)") (p "The " (tt "___pointer") " argument marker disables automatic simplification of pointers to numbers: normally arguments of type " (tt "int *") " are handled as SRFI-4 " (tt "s32vector") " number vectors. To force treatment as a pointer argument, precede the argument type with " (tt "___pointer") ".")) (section 3 "C notes" (p "Foreign variable definitions for macros are not exported from the current compilation unit, but definitions for C variables and functions are.") (p (tt "foreign-parse") " does not embed the text into the generated C file, use " (tt "foreign-declare") " for that (or even better, use the " (tt "#>! ... <#") " syntax which does both).") (p "Functions with variable number of arguments are not supported.")) (section 3 "C++ notes" (p "Each C++ class defines a TinyCLOS class, which is a subclass of " (tt "<c++-object>") ". Instances of this class contain a single slot named " (tt "this") ", which holds a pointer to a heap-allocated C++ instance. The name of the TinyCLOS class is obtained by putting the C++ classname between angled brackets (" (tt "<...>") "). TinyCLOS classes are not seen by C++ code.") (p "The C++ constructor is invoked by the " (tt "initialize") " generic, which accepts as many arguments as the constructor. If no constructor is defined, a default-constructor will be provided taking no arguments. To allow creating class instances from pointers created in foreign code, the " (tt "initialize") " generic will optionally accept an arguments list of the form " (tt "'this POINTER") ", where " (tt "POINTER") " is a foreign pointer object. This will create a TinyCLOS instance for the given C++ object.") (p "To release the storage allocated for a C++ instance invoke the " (tt "destroy") " generic (the name can be changed by using the " (tt "destructor_name") " pseudo declaration).") (p "Static member functions are wrapped in a Scheme procedure named " (tt "<class>::<member>") ".") (p "Member variables and non-public member functions are ignored.") (p "Virtual member functions are not seen by C++ code. Overriding a virtual member function with a TinyCLOS method will not work when the member function is called by C++.") (p "Operator functions and default arguments are not supported.") (p "Exceptions must be explicitly handled by user code and may not be thrown beyond an invocation of C++ by Scheme code."))) (section 2 "Authors" (p (int-link "/users/felix winkelmann" "felix winkelmann"))) (section 2 "License" (pre "Copyright (c) 2000-2007, Felix L. Winkelmann\nAll rights reserved.") (pre "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following\nconditions are met:") (pre "  Redistributions of source code must retain the above copyright notice, this list of conditions and the following\n    disclaimer. \n  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following\n    disclaimer in the documentation and/or other materials provided with the distribution. \n  Neither the name of the author nor the names of its contributors may be used to endorse or promote\n    products derived from this software without specific prior written permission. ") (pre "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\nOTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.")) (section 2 "Version History" (dl (dt "1.99.6") (dd "fixed broken handling of \"___pointer\"") (dt "1.99.5") (dd "fixed use of removed " (tt "pointer") " type in CHICKEN 4.6.4") (dt "1.99.4") (dd "changed category to " (tt "obsolete")) (dt "1.99.3") (dd "added regex dependency") (dt "1.99.2") (dd "use " (tt "regex") " as extension, not unit (for CHICKEN 4.6.3)") (dt "1.97") (dd "removed " (tt "-host") " option from setup script") (dt "1.96") (dd "fixed bug in warning message that caused " (tt "sprintf") " expansion to fail") (dt "1.91") (dd "fixed number parsing bug [Thanks to Shawn Rutledge]") (dt "1.9") (dd "removed use of obsolete reader hack") (dt "1.8") (dd "removed deprecated " (tt "___callback")) (dt "1.7") (dd "added " (tt "chicken-wrap") " tool") (dt "1.6") (dd "fixed error in handling of base constructors [Thanks to Carlos Pita]") (dt "1.5") (dd "added " (tt "foreign-include-path") " [this missing interface was reported by Carlos Pita]") (dt "1.4") (dd "fixed bug in parser that ignored preprocessor commands in some situations [Thanks to Tony Sidaway]") (dt "1.3") (dd "struct-member write-access uses SRFI-17 " (tt "set!")) (dt "1.2") (dd "handles " (tt "#define ID (NUM)") " and shows output in compiler with " (tt "-debug F")) (dt "1.1") (dd "simplified .setup script") (dt "1.0") (dd "moved from base distribution into separate extension"))))