diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/inside/embedding.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/inside/embedding.scrbl new file mode 100644 index 0000000000..fdb491a4f7 --- /dev/null +++ b/pkgs/racket-pkgs/racket-doc/scribblings/inside/embedding.scrbl @@ -0,0 +1,340 @@ +#lang scribble/doc +@(require "utils.rkt") + +@(define cgc-v-3m "CGC versus 3m") + +@title[#:tag "embedding"]{Embedding into a Program} + +@section-index["embedding Racket"] + +The Racket run-time system can be embedded into a larger program. The +embedding process for Racket CGC or Racket 3m (see @secref[cgc-v-3m]) +is essentially the same, but the process for Racket 3m is most easily +understood as a variant of the process for Racket CGC. + +@section{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. + + On 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. + + On 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.) + + On 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.) + + On 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); +} +} + +On Mac OS X, or on 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. + +On 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. + + +@section{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{On 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{On 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{On 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. + +@; ---------------------------------------- +@include-section["hooks.scrbl"] diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/inside/extensions.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/inside/extensions.scrbl new file mode 100644 index 0000000000..64d96a3195 --- /dev/null +++ b/pkgs/racket-pkgs/racket-doc/scribblings/inside/extensions.scrbl @@ -0,0 +1,250 @@ +#lang scribble/doc +@(require "utils.rkt") + +@title[#:tag "Writing Racket Extensions"]{Writing Racket Extensions} + +@section-index["extending Racket"] + +As noted in @secref["embedding-and-extending"], writing Racket code +and using the @seclink["top" #:doc '(lib +"scribblings/foreign/foreign.scrbl")]{foreign-function interface} is +usually a better option than writing an extension to Racket, but +Racket also supports C-implemented extensions that plug more directly +into the run-time system. + +The process of creating an extension for Racket 3m or Racket CGC (see +@secref["CGC versus 3m"]) is essentially the same, but the process for +3m is most easily understood as a variant of the process for CGC. + +@section{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 in a + given @|tech-place|; 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 in a given @|tech-place|. 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"]); even then, such static variables must be +thread-local (in the OS-thread sense) to work with multiple +@|tech-place|s (see @secref["places"]). + +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 on 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. + +@section{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 on 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_3m.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. + +@section{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")] + +@; ---------------------------------------------------------------------- + diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/inside/inside.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/inside/inside.scrbl index c75d98d7b2..4a99e44512 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/inside/inside.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/inside/inside.scrbl @@ -6,21 +6,23 @@ @author["Matthew Flatt"] -This manual describes Racket's C interface, which allows the -interpreter to be extended by a dynamically-loaded library, or -embedded within an arbitrary C/C++ program. The manual assumes -familiarity with Racket as described in @|Racket|. - -For an alternative way of dealing with foreign code, see -@other-manual['(lib "scribblings/foreign/foreign.scrbl")], which -describes the @racketmodname[ffi/unsafe] module for manipulating -low-level libraries and structures purely through Racket code. +This manual describes the C interface of Racket's run-time system. The +C interface is relevant primarily when interacting with foreign +libraries as described in @other-manual['(lib +"scribblings/foreign/foreign.scrbl")]; even though interactions with +foreign code are constructed in pure Racket using the +@racketmodname[ffi/unsafe] module, many details of representations, +memory management, and concurrency are described here. This manual +also describes embedding the Racket run-time system in larger programs +and extending Racket directly with C-implemented libraries. @table-of-contents[] @; ------------------------------------------------------------------------ @include-section["overview.scrbl"] +@include-section["embedding.scrbl"] +@include-section["extensions.scrbl"] @include-section["values.scrbl"] @include-section["memory.scrbl"] @include-section["namespaces.scrbl"] @@ -38,7 +40,6 @@ low-level libraries and structures purely through Racket code. @include-section["custodians.scrbl"] @include-section["subprocesses.scrbl"] @include-section["misc.scrbl"] -@include-section["hooks.scrbl"] @; ------------------------------------------------------------------------ diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/inside/memory.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/inside/memory.scrbl index 575c37e475..3216964a9b 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/inside/memory.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/inside/memory.scrbl @@ -6,9 +6,9 @@ @section-index{memory} @section-index{garbage collection} -Racket uses both @cppi{malloc} and allocation functions provided -by a garbage collector. Embedding/extension C/C++ code may use either -allocation method, keeping in mind that pointers to +Racket uses both @cppi{malloc} and allocation functions provided by a +garbage collector. Foreign-function and embedding/extension C code may +use either allocation method, keeping in mind that pointers to garbage-collectable blocks in @cpp{malloc}ed memory are invisible (i.e., such pointers will not prevent the block from being garbage-collected). diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/inside/overview.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/inside/overview.scrbl index 51438de9cb..987adac772 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/inside/overview.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/inside/overview.scrbl @@ -3,13 +3,27 @@ @title[#:tag "overview"]{Overview} +The Racket run-time system is responsible for the implementation +primitive datatypes such as numbers and strings, the evaluation and/or +JIT compilation of Racket bytecode, the macro expansion and +compilation of Racket from source to bytecode, the allocation and +reclamation of memory used during evaluation, and the scheduling +concurrent threads and parallel tasks. + +Much of the language provided by @racketmodname[racket/base] is +implemented in a more primitive dialect of Racket that is provided by +the run-time system. Future versions of Racket are likely to move +macro expansion, compilation, and many ``primitive'' functions into +such Racket-implemented libraries, instead of having them built into +the run-time system. + @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_}. +defined in this manual start with @cpp{scheme_}. In principle, they +all should be renamed to start @cpp{racket_}. @; ---------------------------------------------------------------------- @@ -23,14 +37,19 @@ libraries. The normal Racket distribution does not include the C sources for Racket's run-time system. To build Racket from scratch, download a -source distribution, or get the latest from the @tt{git} repository at -@url{https://github.com/plt/racket}. Detailed build instructions are -in the @filepath{README} file in the top-level @filepath{src} -directory. +source distribution from @url{http://download.racket-lang.org}; +detailed build instructions are in the @filepath{README} file in the +top-level @filepath{src} directory. You can also get the latest +sources from the @tt{git} repository at +@url{https://github.com/plt/racket}, but beware that the repository is +one step away from a normal source distribution, and it provides build +modes that are more suitable for developing Racket itself; see +@filepath{INSTALL.txt} in the @tt{git} repository for more +information. @; ---------------------------------------------------------------------- -@section{CGC versus 3m} +@section[#:tag "CGC versus 3m"]{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 @@ -38,16 +57,18 @@ 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 +@item{@bold{@as-index{3m}} : the main variant of Racket, which uses + @defterm{precise} garbage collection and requires explicit + registration of pointer roots and allocation shapes. The precise + garbage collector may move its 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.} + platforms) static variables, and it does not move allocated + objects.} ] @@ -56,578 +77,26 @@ At the C level, working with CGC can be much easier than working with @; ---------------------------------------------------------------------- -@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 in a - given @|tech-place|; 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 in a given @|tech-place|. 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"]); even then, such static variables must be -thread-local (in the OS-thread sense) to work with multiple -@|tech-place|s (see @secref["places"]). - -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 on 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 on 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_3m.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. - - On 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. - - On 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.) - - On 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.) - - On 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); -} -} - -On Mac OS X, or on 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. - -On 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{On 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{On 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{On 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[#:tag "embedding-and-extending"]{Embedding and Extending Racket} + +The Racket run-time system can be embedded into a larger program; see +@secref["embedding"] for more information. As an alternative to +embedding, the @exec{racket} executable can also be run in a +subprocess, and that choice may be better for many purposes. On +Windows, @seclink["top" #:doc '(lib "mzcom/mzcom.scrbl") #:indirect? +#t]{MzCom} provides another option. + +The Racket run-time system @seclink["Writing Racket Extensions"]{can +be extended} with new C-implemented functions. Historically, writing +an extension could provide performance benefits relative to writing +pure Racket code, but Racket performance has improved to the point +that performance benefits of writing C code (if any) are usually too +small to justify the maintenance effort. For calling functions that +are provided by a C-implemented library, meanwhile, using with +@seclink["top" #:doc '(lib +"scribblings/foreign/foreign.scrbl")]{foreign-function interface} +within Racket is a better choice than writing an extension of Racket +to call the library. @; ---------------------------------------------------------------------- @@ -639,17 +108,18 @@ memory cannot be communicated from one place to another, because such pointers in one place are invisible to the memory manager of another place. -When @|tech-place| support is enabled, static variables in an -extension or an embedding generally cannot hold pointers to GC-managed -memory, since the static variable may be used from multiple places. -For some OSes, a static variable can be made thread-local, in which -case it has a different address in each OS thread, and each different -address can be registered with the GC for a given place. +When @|tech-place| support is enabled, static variables at the C level +generally cannot hold pointers to GC-managed memory, since the static +variable may be used from multiple places. For some OSes, a static +variable can be made thread-local, in which case it has a different +address in each OS thread, and each different address can be +registered with the GC for a given place. -The OS thread that originally calls @cpp{scheme_basic_env} is the OS -thread of the original place. 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 +In an @seclink["embedding"]{embedding application}, the OS thread that +originally calls @cpp{scheme_basic_env} is the OS thread of the +original place. 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, the new thread is the OS thread for the original place. @@ -665,17 +135,17 @@ 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 representing a -particular @|tech-place| can call @cpp{scheme_} functions. (This -restriction is stronger than saying all calls for a given place must -be serialized across threads. Racket relies on properties of specific -threads to avoid stack overflow and garbage collection.) For the -original place, only the OS thread used to call @cpp{scheme_basic_env} -can call @cpp{scheme_} functions. For any other place, only the OS -thread that is created by Racket for the place can be used to call -@cpp{scheme_} functions. +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 representing a particular @|tech-place| can call +@cpp{scheme_} functions. (This restriction is stronger than saying all +calls for a given place must be serialized across threads. Racket +relies on properties of specific threads to avoid stack overflow and +garbage collection.) In an @seclink["embedding"]{embedding +application}, for the original place, only the OS thread used to call +@cpp{scheme_basic_env} can call @cpp{scheme_} functions. For any other +place, only the OS thread that is created by Racket for the place can +be used to call @cpp{scheme_} functions. See @secref["threads"] for more information about threads, including the possible effects of Racket's thread implementation on extension