#lang scribble/doc
@(require "utils.ss")

@title[#:tag "overview"]{Overview}

@section{``Scheme'' versus ``Racket''}

The old name for Racket was ``PLT Scheme,'' and the core compiler and
run-time system used to be called ``MzScheme.'' The old names are
entrenched in Racket internals, to the point that most C bindings
defined in this manual start with @cpp{scheme_}. They all should be
renamed to start @cpp{racket_}.

@; ----------------------------------------------------------------------

@section{CGC versus 3m}

Before mixing any C code with Racket, first decide whether to use the
@bold{3m} variant of Racket, the @bold{CGC} variant of Racket, or
both:

@itemize[

@item{@bold{@as-index{3m}} : the main variant of Racket, which
  uses @defterm{precise} garbage collection instead of conservative
  garbage collection, and it may move objects in memory during a
  collection.}

@item{@bold{@as-index{CGC}} : the original variant of Racket, where
  memory management depends on a @defterm{conservative} garbage
  collector. The conservative garbage collector can automatically find
  references to managed values from C local variables and (on some
  platforms) static variables.}

]

At the C level, working with CGC can be much easier than working with
3m, but overall system performance is typically better with 3m.

@; ----------------------------------------------------------------------

@section{Writing Racket Extensions}

@section-index["extending Racket"]

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

@subsection{CGC Extensions}


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

@itemize[

 @item{@index['("header files")]{For} each C/C++ file that uses
 Racket library functions, @cpp{#include} the file
 @as-index{@filepath{escheme.h}}.

 This file is distributed with the Racket software in an
 @filepath{include} directory, but if @|mzc| is used to
 compile, this path is found automatically.}


 @item{Define the C function @cppi{scheme_initialize}, which takes a
 @cpp{Scheme_Env*} namespace (see @secref["im:env"]) and returns a
 @cpp{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 @racket[load-extension] (the first time);
 the return value from @cpp{scheme_initialize} is used as the return
 value for @racket[load-extension]. The namespace provided to
 @cpp{scheme_initialize} is the current namespace when
 @racket[load-extension] is called.}


 @item{Define the C function @cppi{scheme_reload}, which has the same
 arguments and return type as @cpp{scheme_initialize}.

 This function is called if @racket[load-extension] is called a second
 time (or more times) for an extension. Like @cpp{scheme_initialize},
 the return value from this function is the return value for
 @racket[load-extension].}


 @item{Define the C function @cppi{scheme_module_name}, which takes
 no arguments and returns a @cpp{Scheme_Object*} value, either a
 symbol or @cpp{scheme_false}.

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

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


 @item{Compile the extension C/C++ files to create platform-specific
 object files.

 The @as-index{@|mzc|} compiler, which is distributed with Racket,
 compiles plain C files when the @as-index{@DFlag{cc}} flag is
 specified. More precisely, @|mzc| 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 @exec{gcc} in the path, or a Mac OS X system with Apple's
 developer tools installed, then using @|mzc| is typically easier than
 working with the C compiler directly. Use the @as-index{@DFlag{cgc}}
 flag to indicate that the build is for use with Racket CGC.}


 @item{Link the extension C/C++ files with
 @as-index{@filepath{mzdyn.o}} (Unix, Mac OS X) or
 @as-index{@filepath{mzdyn.obj}} (Windows) to create a shared object. The
 resulting shared object should use the extension @filepath{.so} (Unix),
 @filepath{.dll} (Windows), or @filepath{.dylib} (Mac OS X).

 The @filepath{mzdyn} object file is distributed in the installation's
 @filepath{lib} directory. For Windows, the object file is in a
 compiler-specific sub-directory of @filepath{racket\lib}.

 The @|mzc| compiler links object files into an extension when the
 @as-index{@DFlag{ld}} flag is specified, automatically locating
 @filepath{mzdyn}. Again, use the @DFlag{cgc} flag with @|mzc|.}

 @item{Load the shared object within Racket using
 @racket[(load-extension _path)], where @racket[_path] is the name of
 the extension file generated in the previous step.

 Alternately, if the extension defines a module (i.e.,
 @cpp{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 @racket[require] is used. The
 special directory is a platform-specific path that can be obtained by
 evaluating @racket[(build-path "compiled" "native"
 (system-library-subpath))]; see @racket[load/use-compiled] for more
 information.  For example, if the shared object's name is
 @filepath{example_rkt.dll}, then @racket[(require "example.rkt")] will
 be redirected to @filepath{example_rkt.dll} if the latter is placed in
 the sub-directory @racket[(build-path "compiled" "native"
 (system-library-subpath))] and if @filepath{example.rkt} does not
 exist or has an earlier timestamp.

 Note that @racket[(load-extension _path)] within a @racket[module]
 does @italic{not} introduce the extension's definitions into the
 module, because @racket[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
 @racket[require].}

]

@index['("allocation")]{@bold{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 @cppi{scheme_malloc}. However,
static variables that contain pointers to collectable memory must be
registered using @cppi{scheme_register_extension_global} (see
@secref["im:memoryalloc"]).

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

@verbatim[#:indent 2]{
 #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 @filepath{hw.c}, the extension
is compiled under Unix with the following two commands:

@commandline{raco ctool --cgc --cc hw.c}
@commandline{raco ctool --cgc --ld hw.so hw.o}

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

The @filepath{collects/mzscheme/examples} directory in the Racket
distribution contains additional examples.

@subsection{3m Extensions}

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

@itemize[

 @item{Adjust code to cooperate with the garbage collector as
 described in @secref["im:3m"]. Using @|mzc| with the
 @as-index{@DFlag{xform}} might convert your code to implement part of
 the conversion, as described in @secref["im:3m:mzc"].}

 @item{In either your source in the in compiler command line,
 @cpp{#define} @cpp{MZ_PRECISE_GC} before including
 @filepath{escheme.h}. When using @|mzc| with the @DFlag{cc} and
 @as-index{@DFlag{3m}} flags, @cpp{MZ_PRECISE_GC} is automatically
 defined.}

 @item{Link with @as-index{@filepath{mzdyn3m.o}} (Unix, Mac OS X) or
 @as-index{@filepath{mzdyn3m.obj}} (Windows) to create a shared
 object.  When using @|mzc|, use the @DFlag{ld} and @DFlag{3m} flags
 to link to these libraries.}

]

For a relatively simple extension @filepath{hw.c}, the extension is
compiled under Unix for 3m with the following three commands:

@commandline{raco ctool --xform hw.c}
@commandline{raco ctool --3m --cc hw.3m.c}
@commandline{raco ctool --3m --ld hw.so hw.o}

Some examples in @filepath{collects/mzscheme/examples} work with
Racket 3m in this way. A few examples are manually instrumented, in
which case the @DFlag{xform} step should be skipped.

@subsection{Declaring a Module in an Extension}

To create an extension that behaves as a module, return a symbol from
@cpp{scheme_module_name}, and have @cpp{scheme_initialize} and
@cpp{scheme_rename} declare a module using @cpp{scheme_primitive_module}.

For example, the following extension implements a module named
@racket[hello] that exports a binding @racket[greeting]:

@verbatim[#:indent 2]{
  #include "escheme.h"

  Scheme_Object *scheme_initialize(Scheme_Env *env) {
    Scheme_Env *mod_env;
    mod_env = scheme_primitive_module(scheme_intern_symbol("hi"), 
                                      env);
    scheme_add_global("greeting", 
                      scheme_make_utf8_string("hello"), 
                      mod_env);
    scheme_finish_primitive_module(mod_env);
    return scheme_void;
  }

  Scheme_Object *scheme_reload(Scheme_Env *env) {
    return scheme_initialize(env); /* Nothing special for reload */
  }

  Scheme_Object *scheme_module_name() {
    return scheme_intern_symbol("hi");
  }
}

This extension could be compiled for 3m on i386 Linux, for
example, using the following sequence of @exec{mzc} commands:

@commandline{raco ctool --xform hi.c}
@commandline{raco ctool --3m --cc hi.3m.c}
@commandline{mkdir -p compiled/native/i386-linux/3m}
@commandline{raco ctool --3m --ld compiled/native/i386-linux/3m/hi_rkt.so hi_3m.o}

The resulting module can be loaded with

@racketblock[(require "hi.rkt")]

@; ----------------------------------------------------------------------

@section[#:tag "embedding"]{Embedding Racket into a Program}

@section-index["embedding Racket"]

Like creating extensions, the embedding process for Racket CGC or
Racket 3m is essentially the same, but the process for Racket
3m is most easily understood as a variant of the process for
Racket CGC.

@subsection{CGC Embedding}

To embed Racket CGC in a program, follow these steps:

@itemize[

 @item{Locate or build the Racket CGC libraries. Since the
  standard distribution provides 3m libraries, only, you will most
  likely have to build from source.

  Under Unix, the libraries are @as-index{@filepath{libracket.a}}
  and @as-index{@filepath{libmzgc.a}} (or
  @as-index{@filepath{libracket.so}} and
  @as-index{@filepath{libmzgc.so}} for a dynamic-library build, with
  @as-index{@filepath{libracket.la}} and
  @as-index{@filepath{libmzgc.la}} files for use with
  @exec{libtool}). Building from source and installing places the
  libraries into the installation's @filepath{lib} directory. Be sure
  to build the CGC variant, since the default is 3m.

  Under Windows, stub libraries for use with Microsoft tools are
  @filepath{libracket@italic{x}.lib} and
  @filepath{libmzgc@italic{x}.lib} (where @italic{x} represents the
  version number) are in a compiler-specific directory in
  @filepath{racket\lib}. These libraries identify the bindings that are
  provided by @filepath{libracket@italic{x}.dll} and
  @filepath{libmzgc@italic{x}.dll} --- which are typically installed
  in @filepath{racket\lib}. When linking with Cygwin, link to
  @filepath{libracket@italic{x}.dll} and
  @filepath{libmzgc@italic{x}.dll} directly.  At run time, either
  @filepath{libracket@italic{x}.dll} and
  @filepath{libmzgc@italic{x}.dll} must be moved to a location in the
  standard DLL search path, or your embedding application must
  ``delayload'' link the DLLs and explicitly load them before
  use. (@filepath{Racket.exe} and @filepath{GRacket.exe} use the latter
  strategy.)

  Under Mac OS X, dynamic libraries are provided by the
  @filepath{Racket} framework, which is typically installed in
  @filepath{lib} sub-directory of the installation. Supply
  @exec{-framework Racket} to @exec{gcc} when linking, along
  with @exec{-F} and a path to the @filepath{lib} directory. Beware
  that CGC and 3m libraries are installed as different versions within
  a single framework, and installation marks one version or the other
  as the default (by setting symbolic links); install only CGC to
  simplify accessing the CGC version within the framework.  At run
  time, either @filepath{Racket.framework} must be moved to a
  location in the standard framework search path, or your embedding
  executable must provide a specific path to the framework (possibly
  an executable-relative path using the Mach-O @tt["@executable_path"]
  prefix).}

 @item{For each C/C++ file that uses Racket library functions,
  @cpp{#include} the file @as-index{@filepath{scheme.h}}.

  The C preprocessor symbol @cppi{SCHEME_DIRECT_EMBEDDED} is defined
  as @cpp{1} when @filepath{scheme.h} is @cpp{#include}d, or as
  @cpp{0} when @filepath{escheme.h} is @cpp{#include}d.

  The @filepath{scheme.h} file is distributed with the Racket software in
  the installation's @filepath{include} directory. Building and
  installing from source also places this file in the installation's
  @filepath{include} directory.}

 @item{Start your main program through the @cpp{scheme_main_setup} (or
  @cpp{scheme_main_stack_setup}) trampoline, and put all uses of
  Racket functions inside the function passed to
  @cpp{scheme_main_setup}. The @cpp{scheme_main_setup} function
  registers the current C stack location with the memory manager. It
  also creates the initial namespace @cpp{Scheme_Env*} by calling
  @cppi{scheme_basic_env} and passing the result to the function
  provided to @cpp{scheme_main_setup}. (The
  @cpp{scheme_main_stack_setup} trampoline registers the C stack with
  the memory manager without creating a namespace.)

  Under 32-bit Windows, when support for parallelism is enabled in the Racket
  build (as is the default), then before calling
  @cpp{scheme_main_setup}, your embedding application must first call
  @cppi{scheme_register_tls_space}:

  @verbatim[#:indent 2]{
   scheme_register_tls_space(&tls_space, 0);
  }

  where @cpp{tls_space} is declared as a thread-local pointer variable
  in the main executable (i.e., not in a dynamically linked DLL):

  @verbatim[#:indent 2]{
   static __declspec(thread) void *tls_space;
  }}

 @item{Configure the namespace by adding module declarations. The
  initial namespace contains declarations only for a few primitive
  modules, such as @racket['#%kernel], and no bindings are imported
  into the top-level environment.

  To embed a module like @racketmodname[racket/base] (along with all
  its dependencies), use @exec{raco ctool --c-mods}, which generates a C file
  that contains modules in bytecode form as encapsulated in a static
  array. The generated C file defines a @cppi{declare_modules}
  function that takes a @cpp{Scheme_Env*}, installs the modules into
  the environment, and adjusts the module name resolver to access the
  embedded declarations.

  Alternately, use @cpp{scheme_set_collects_path} and
  @cpp{scheme_init_collection_paths} to configure and install a path
  for finding modules at run time.}

 @item{Access Racket through @cppi{scheme_dynamic_require},
  @cppi{scheme_load}, @cppi{scheme_eval}, and/or other functions
  described in this manual.

  If the embedding program configures built-in parameters in a way
  that should be considered part of the default configuration, then
  call @cpp{scheme_seal_parameters} afterward. The snapshot of
  parameter values taken by @cpp{scheme_seal_parameters} is used for
  certain privileged operations, such as installing a @|PLaneT|
  package.}

 @item{Compile the program and link it with the Racket libraries.}

]

@index['("allocation")]{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 @cppi{scheme_malloc}. In an embedding
application on some platforms, static variables are also automatically
registered as roots for garbage collection (but see notes below
specific to Mac OS X and Windows).

For example, the following is a simple embedding program which
evaluates all expressions provided on the command line and displays
the results, then runs a @racket[read]-@racket[eval]-@racket[print]
loop. Run

@commandline{raco ctool --c-mods base.c ++lib racket/base}

to generate @filepath{base.c}, which encapsulates @racket[racket/base]
and all of its transitive imports (so that they need not be found
separately a run time).

@verbatim[#:indent 2]{
#include "scheme.h"

#include "base.c"

static int run(Scheme_Env *e, int argc, char *argv[])
{
  Scheme_Object *curout;
  int i;
  mz_jmp_buf * volatile save, fresh;

  /* Declare embedded modules in "base.c": */
  declare_modules(e);

  scheme_namespace_require(scheme_intern_symbol("racket/base"));

  curout = scheme_get_param(scheme_current_config(), 
                            MZCONFIG_OUTPUT_PORT);

  for (i = 1; i < argc; i++) {
    save = scheme_current_thread->error_buf;
    scheme_current_thread->error_buf = &fresh;
    if (scheme_setjmp(scheme_error_buf)) {
      scheme_current_thread->error_buf = save;
      return -1; /* There was an error */
    } else {
      Scheme_Object *v, *a[2];
      v = scheme_eval_string(argv[i], e);
      scheme_display(v, curout);
      scheme_display(scheme_make_char('\n'), curout);
      /* read-eval-print loop, uses initial Scheme_Env: */
      a[0] = scheme_intern_symbol("racket/base");
      a[1] = scheme_intern_symbol("read-eval-print-loop");
      scheme_apply(scheme_dynamic_require(2, a), 0, NULL);
      scheme_current_thread->error_buf = save;
    }
  }
  return 0;
}

int main(int argc, char *argv[])
{
  return scheme_main_setup(1, run, argc, argv);
}
}

Under Mac OS X, or under Windows when Racket is compiled to a DLL
using Cygwin, the garbage collector cannot find static variables
automatically. In that case, @cppi{scheme_main_setup} must be called with a
non-zero first argument.

Under Windows (for any other build mode), the garbage collector finds
static variables in an embedding program by examining all memory
pages. This strategy fails if a program contains multiple Windows
threads; a page may get unmapped by a thread while the collector is
examining the page, causing the collector to crash. To avoid this
problem, call @cpp{scheme_main_setup} with a non-zero first argument.

When an embedding application calls @cpp{scheme_main_setup} with a non-zero
first argument, it must register each of its static variables with
@cppi{MZ_REGISTER_STATIC} if the variable can contain a GCable
pointer. For example, if @cpp{curout} above is made @cpp{static}, then
@cpp{MZ_REGISTER_STATIC(curout)} should be inserted before the call to
@cpp{scheme_get_param}.

When building an embedded Racket CGC to use SenoraGC (SGC) instead of
the default collector, @cpp{scheme_main_setup} must be called with a
non-zero first argument.  See @secref["im:memoryalloc"] for more
information.


@subsection{3m Embedding}

Racket 3m can be embedded mostly the same as Racket, as long as the
embedding program cooperates with the precise garbage collector as
described in @secref["im:3m"].

In either your source in the in compiler command line, @cpp{#define}
@cpp{MZ_PRECISE_GC} before including @filepath{scheme.h}. When using
@|mzc| with the @DFlag{cc} and @DFlag{3m} flags, @cpp{MZ_PRECISE_GC}
is automatically defined.

In addition, some library details are different:

@itemize[

 @item{Under Unix, the library is just
  @as-index{@filepath{libracket3m.a}} (or
  @as-index{@filepath{libracket3m.so}} for a dynamic-library build,
  with @as-index{@filepath{libracket3m.la}} for use with
  @exec{libtool}). There is no separate library for 3m analogous to
  CGC's @filepath{libmzgc.a}.}

 @item{Under Windows, the stub library for use with Microsoft tools is
  @filepath{libracket3m@italic{x}.lib} (where @italic{x} represents the
  version number). This library identifies the bindings that are
  provided by @filepath{libracket3m@italic{x}.dll}.  There is no
  separate library for 3m analogous to CGC's
  @filepath{libmzgc@italic{x}.lib}.}

  @item{Under Mac OS X, 3m dynamic libraries are provided by the
  @filepath{Racket} framework, just as for CGC, but as a version
  suffixed with @filepath{_3m}.}

]

For Racket 3m, an embedding application must call @cpp{scheme_main_setup}
with a non-zero first argument.

The simple embedding program from the previous section can be
processed by @exec{raco ctool --xform}, then compiled and linked with
Racket 3m.  Alternately, the source code can be extended to work with
either CGC or 3m depending on whether @cpp{MZ_PRECISE_GC} is defined
on the compiler's command line:

@verbatim[#:indent 2]{
#include "scheme.h"

#include "base.c"

static int run(Scheme_Env *e, int argc, char *argv[])
{
  Scheme_Object *curout = NULL, *v = NULL, *a[2] = {NULL, NULL};
  Scheme_Config *config = NULL;
  int i;
  mz_jmp_buf * volatile save = NULL, fresh;

  MZ_GC_DECL_REG(8);
  MZ_GC_VAR_IN_REG(0, e);
  MZ_GC_VAR_IN_REG(1, curout);
  MZ_GC_VAR_IN_REG(2, save);
  MZ_GC_VAR_IN_REG(3, config);
  MZ_GC_VAR_IN_REG(4, v);
  MZ_GC_ARRAY_VAR_IN_REG(5, a, 2);

  MZ_GC_REG();

  declare_modules(e);

  v = scheme_intern_symbol("racket/base");
  scheme_namespace_require(v);

  config = scheme_current_config();
  curout = scheme_get_param(config, MZCONFIG_OUTPUT_PORT);

  for (i = 1; i < argc; i++) {
    save = scheme_current_thread->error_buf;
    scheme_current_thread->error_buf = &fresh;
    if (scheme_setjmp(scheme_error_buf)) {
      scheme_current_thread->error_buf = save;
      return -1; /* There was an error */
    } else {
      v = scheme_eval_string(argv[i], e);
      scheme_display(v, curout);
      v = scheme_make_char('\n');
      scheme_display(v, curout);
      /* read-eval-print loop, uses initial Scheme_Env: */
      a[0] = scheme_intern_symbol("racket/base");
      a[1] = scheme_intern_symbol("read-eval-print-loop");
      v = scheme_dynamic_require(2, a);
      scheme_apply(v, 0, NULL);
      scheme_current_thread->error_buf = save;
    }
  }

  MZ_GC_UNREG();

  return 0;
}

int main(int argc, char *argv[])
{
  return scheme_main_setup(1, run, argc, argv);
}
}

Strictly speaking, the @cpp{config} and @cpp{v} variables above need
not be registered with the garbage collector, since their values are
not needed across function calls that allocate. The code is much
easier to maintain, however, when all local variables are registered
and when all temporary values are put into variables.

@; ----------------------------------------------------------------------

@section{Racket and Threads}

Racket implements threads for Racket programs without aid from the
operating system, so that Racket threads are cooperative from the
perspective of C code. Under Unix, stand-alone Racket uses a single
OS-implemented thread. Under Windows and Mac OS X, stand-alone
Racket uses a few private OS-implemented threads for background
tasks, but these OS-implemented threads are never exposed by the
Racket API.

In an embedding application, Racket can co-exist with additional
OS-implemented threads, but the additional OS threads must not call
any @cpp{scheme_} function.  Only the OS thread that originally calls
@cpp{scheme_basic_env} can call @cpp{scheme_} functions. (This
restriction is stronger than saying all calls must be serialized
across threads. Racket relies on properties of specific threads to
avoid stack overflow and garbage collection.) When
@cpp{scheme_basic_env} is called a second time to reset the
interpreter, it can be called in an OS thread that is different from
the original call to @cpp{scheme_basic_env}. Thereafter, all calls to
@cpp{scheme_} functions must originate from the new thread.

See @secref["threads"] for more information about threads, including
the possible effects of Racket's thread implementation on extension
and embedding C code.

@; ----------------------------------------------------------------------

@section[#:tag "im:unicode"]{Racket, Unicode, Characters, and Strings}

A character in Racket is a Unicode code point. In C, a character
value has type @cppi{mzchar}, which is an alias for @cpp{unsigned} ---
which is, in turn, 4 bytes for a properly compiled Racket. Thus, a
@cpp{mzchar*} string is effectively a UCS-4 string.

Only a few Racket functions use @cpp{mzchar*}. Instead, most
functions accept @cpp{char*} strings. When such byte strings are to be
used as a character strings, they are interpreted as UTF-8
encodings. A plain ASCII string is always acceptable in such cases,
since the UTF-8 encoding of an ASCII string is itself.

See also @secref["im:strings"] and @secref["im:encodings"].

@; ----------------------------------------------------------------------

@section[#:tag "im:intsize"]{Integers}

Racket expects to be compiled in a mode where @cppi{short} is a
16-bit integer, @cppi{int} is a 32-bit integer, and @cppi{intptr_t} has
the same number of bits as @cpp{void*}. The @cppi{long} type can match
either @cpp{int} or @cpp{intptr_t}, depending on the platform.
The @cppi{mzlonglong} type has
64 bits for compilers that support a 64-bit integer type, otherwise it
is the same as @cpp{intptr_t}; thus, @cpp{mzlonglong} tends to match
@cpp{long long}. The @cppi{umzlonglong} type is the unsigned version
of @cpp{mzlonglong}.
