4.1 Linking your libraries to the virtual machine
A nice thing you can do with GNU Smalltalk is enhancing it with your
own goodies. If they're written in Smalltalk only, no problem:
getting them to work as packages (see section 3.7 Packages), and to fit
in with the GNU Smalltalk packaging system, is likely to be a
five-minutes task.
If your goodie is mostly written in C and you don't need particular
glue to link it to Smalltalk (for example, there are no callbacks from
C code to Smalltalk code), you can use the dynamic library linking
system. When using this system, you have to link GNU Smalltalk with the library
at run-time using DLD; the method to be used here is
DLD class>>#addLibrary: .
But if you want to provide a more intimate link between C and Smalltalk,
as is the case with Blox, you should use the dynamic module
linking system. This section explains what to do, taking the Blox
library as a guide.
Modules are searched for in the `gnu-smalltalk' subdirectory
of the system library path, or in the directory that the
SMALLTALK_MODULES environment variable points to.
A module is distinguished from a standard shared library because
it has a function which Smalltalk calls to initialize the module;
the name of this function must be gst_initModule . Here is
the initialization function used by Blox:
| void
gst_initModule(proxy)
VMProxy *proxy;
{
vmProxy = proxy;
vmProxy->defineCFunc("Tcl_Eval", Tcl_Eval);
vmProxy->defineCFunc("Tcl_GetStringResult", Tcl_GetStringResult);
vmProxy->defineCFunc("tclInit", tclInit);
vmProxy->defineCFunc("bloxIdle", bloxIdle);
}
|
Note that the defineCFunc function is called through a
function pointer in gst_initModule , and that Blox saves
the value of its parameter to be used elsewhere in its code.
This is not strictly necessary on many platforms, namely those
where the module is effectively linked with the Smalltalk
virtual machine at run-time; but since some(9) cannot obtain this, for maximum portability
you must always call the virtual machine through the proxy and
never refer to any symbol which the virtual machine exports.
For uniformity, even programs that link with `libgst.a' should
not call these functions directly, but through a VMProxy
exported by `libgst.a' and accessible through the
interpreterProxy variable.
First of all, you have to build your package as a shared library; using
GNU Automake and libtool , this is as easy as changing your
`Makefile.am' file so that it reads like this
| pkglib_LTLIBRARIES = libblox.la
libblox_la_LDFLAGS = -module -no-undefined ... more flags ...
libblox_la_SOURCES = ... your source files ...
|
instead of reading like this
| pkglib_LIBRARIES = libblox.a
libblox_a_LDFLAGS = ... more flags ...
libblox_a_SOURCES = ... your source files ...
|
As you see, you only have to change `.a' extensions to `.la',
LIBRARIES targets to LTLIBRARIES , and add appropriate
options to LDFLAGS (10). You will also have to run libtoolize and
follow its instruction, but this is really simpler than it looks.
Note that this example uses `pkglib' because TCP is installed
together with Smalltalk, but in general this is not necessary. You can
install the library wherever you want; libtool will even generate
appropriate warnings to the installer if ldconfig (or an equivalent
program) has to be re-run.
Finally, you will have to specify the name of the module
in the `packages' file. In this case, the relevant
entry in that file will be
| Blox
Kernel
Blox.st libblox
../blox
|
Everything not ending with `.st' will be picked by the
package loader as a module, and will be passed to
DLD class>>#addModule: before attempting to file-in
the Smalltalk source files.
|