6.1  Accessing external objects

[syntax] (foreign-code STRING)
Executes the embedded C/C++ code [STRING], which should be a sequence of C statements, which are executed and return an unspecified result.

(foreign-code "doSomeInitStuff();")     =>  #<unspecified>

[syntax] (foreign-value STRING TYPE)
Evaluates the embedded C/C++ expression [STRING], returning a value of type given in the foreign-type specifier [TYPE].

(print (foreign-code "my_version_string" c-string))

[syntax] (define-foreign-type NAME TYPE [ARGCONVERT [RETCONVERT]])
Defines an alias for TYPE. TYPE may be a type-specifier or a string naming a C type. The namespace of foreign type specifiers is separate from the normal Scheme namespace. The optional arguments ARGCONVERT and RETCONVERT should evaluate to procedures that map argument- and result-values to a value that can be transformed to TYPE:

(declare (uses extras))

(define-foreign-type char-vector 
  nonnull-c-string
  (compose list->string vector->list)
  (compose list->vector string->list) )

(define strlen
  (foreign-lambda int "strlen" char-vector) )

(strlen '#(#\a#\b#\c))                      ==> 3

(define memset
  (foreign-lambda char-vector "memset" char-vector char int) )

(memset '#(#\_ #\_ #\_) #\X3)                ==> #(#\X#\X#\X)

Foreign type-definitions are only visible in the compilation-unit in which they are defined, so use include to use the same definitions in multiple files.

[syntax] (define-foreign-variable NAME TYPE [STRING])
Defines a foreign variable of name NAME. STRING should be the real name of a foreign variable or parameterless macro. If STRING is not given, then the variable name NAME will be converted to a string and used instead. All references and assignments (via set!) are modified to correctly convert values between Scheme and C representation. This foreign variable can only be accessed in the current compilation unit, but the name can be lexically shadowed. Note that STRING can name an arbitrary C expression. If no assignments are performed, then STRING doesn't even have to specify an lvalue.

#>
enum { abc=3, def, ghi };
<#

(define-macro (define-foreign-enum . items)
  `(begin
     ,@(map (match-lambda 
              [(name realname) `(define-foreign-variable ,name int ,realname)]
              [name `(define-foreign-variable ,name int)] )
     items) ) )

(define-foreign-enum abc def ghi)

ghi                               ==> 5

[syntax] (foreign-callback-lambda RETURNTYPE NAME ARGTYPE)
This is similar to foreign-lambda, but also allows the called function to call Scheme functions. See 6.4.

[syntax] (foreign-callback-lambda* RETURNTYPE ((ARGTYPE VARIABLE) ...) STRING ...)
This is similar to foreign-lambda*, but also allows the called function to call Scheme functions. See 6.4.

[syntax] (foreign-lambda RETURNTYPE NAME ARGTYPE ...)
Represents a binding to an external routine. This form can be used in the position of an ordinary lambda expression. NAME specifies the name of the external procedure and should be a string or a symbol.

[syntax] (foreign-lambda* RETURNTYPE ((ARGTYPE VARIABLE) ...) STRING ...)
Similar to foreign-lambda, but instead of generating code to call an external function, the body of the C procedure is directly given in STRING ...:

(define my-strlen
  (foreign-lambda* int ((c-string str))
    "int n = 0;
     while(*(str++)) ++n;
     return(n);") )

(my-strlen "one two three")             ==> 13

For obscure technical reasons any use of the return statement should enclose the result value in parentheses. For the same reasons return without an argument is not allowed.