The process of creating an extension for Racket 3m or Racket CGC (see
CGC versus 3m) is essentially the same, but the process for
3m is most easily understood as a variant of the process for CGC.

3.1CGC Extensions

To write a C/C++-based extension for Racket CGC, follow these
steps:

For each C/C++ file that uses
Racket library functions, #include the file
"escheme.h".

This file is distributed with the Racket software in an
"include" directory, but if raco ctool is used to
compile, this path is found automatically.

Define the C function scheme_initialize, which takes a
Scheme_Env* namespace (see Namespaces and Modules) and returns a
Scheme_Object* Racket value.

This initialization function can install new global primitive
procedures or other values into the namespace, or it can simply
return a Racket value. The initialization function is called when the
extension is loaded with load-extension the first time in a
given place; the return value from scheme_initialize is used
as the return value for load-extension. The namespace
provided to scheme_initialize is the current namespace when
load-extension is called.

Define the C function scheme_reload, which has the same
arguments and return type as scheme_initialize.

This function is called if load-extension is called a second
time (or more times) for an extension in a given place. Like
scheme_initialize, the return value from this function is the
return value for load-extension.

Define the C function scheme_module_name, which takes
no arguments and returns a Scheme_Object* value, either a
symbol or scheme_false.

The function should return a symbol when the effect of calling
scheme_initialize and scheme_reload is only to declare
a module with the returned name. This function is called when the
extension is loaded to satisfy a require declaration.

The scheme_module_name function may be called before
scheme_initialize and scheme_reload, after those
functions, or both before and after, depending on how the extension
is loaded and re-loaded.

The raco ctool compiler, which is distributed with Racket,
compiles plain C files when the --cc flag is
specified. More precisely, raco ctool does not compile the files itself,
but it locates a C compiler on the system and launches it with the
appropriate compilation flags. If the platform is a relatively
standard Unix system, a Windows system with either Microsoft’s C
compiler or gcc in the path, or a Mac OS system with Apple’s
developer tools installed, then using raco ctool is typically easier than
working with the C compiler directly. Use the --cgc
flag to indicate that the build is for use with Racket CGC.

The "mzdyn" object file is distributed in the installation’s
"lib" directory. For Windows, the object file is in a
compiler-specific sub-directory of "racket\lib".

The raco ctool compiler links object files into an extension when the
--ld flag is specified, automatically locating
"mzdyn". Again, use the --cgc flag with raco ctool.

Load the shared object within Racket using
(load-extensionpath), where path is the name of
the extension file generated in the previous step.

Alternately, if the extension defines a module (i.e.,
scheme_module_name returns a symbol), then place the shared
object in a special directory with a special name, so that it is
detected by the module loader when require is used. The
special directory is a platform-specific path that can be obtained by
evaluating (build-path"compiled""native"(system-library-subpath)); see load/use-compiled for more
information. For example, if the shared object’s name is
"example_rkt.dll", then (require"example.rkt") will
be redirected to "example_rkt.dll" if the latter is placed in
the sub-directory (build-path"compiled""native"(system-library-subpath)) and if "example.rkt" does not
exist or has an earlier timestamp.

Note that (load-extensionpath) within a module
does not introduce the extension’s definitions into the
module, because load-extension is a run-time operation. To
introduce an extension’s bindings into a module, make sure that the
extension defines a module, put the extension in the
platform-specific location as described above, and use
require.

IMPORTANT: With Racket CGC, Racket
values are garbage collected using a conservative garbage collector,
so pointers to Racket objects can be kept in registers, stack
variables, or structures allocated with scheme_malloc. However,
static variables that contain pointers to collectable memory must be
registered using scheme_register_extension_global (see
Memory Allocation); even then, such static variables must be
thread-local (in the OS-thread sense) to work with multiple
places (see Racket and Places).

As an example, the following C code defines an extension that returns
"hello world" when it is loaded:

#include "escheme.h"

Scheme_Object *scheme_initialize(Scheme_Env *env) {

return scheme_make_utf8_string("hello world");

}

Scheme_Object *scheme_reload(Scheme_Env *env) {

return scheme_initialize(env); /* Nothing special for reload */

}

Scheme_Object *scheme_module_name() {

return scheme_false;

}

Assuming that this code is in the file "hw.c", the extension
is compiled on Unix with the following two commands:

raco ctool --cgc --cc hw.c

raco ctool --cgc --ld hw.so hw.o

(Note that the --cgc, --cc, and --ld flags are each
prefixed by two dashes, not one.)

The "collects/mzscheme/examples" directory in the Racket
distribution contains additional examples.

3.23m Extensions

To build an extension to work with Racket 3m, the CGC instructions
must be extended as follows: