Next: C callout, Up: C and Smalltalk
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 Packages), and to fit in with the GNU Smalltalk packaging system, is likely to be a five-minutes task.
If your goodie is creating a binding to an external C library and you do
not 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, using either
DLD class>>#addLibrary:
or a <library>
tag in a
package.xml file (see Packages). The following line:
DLD addLibrary: 'libc'
is often used to use the standard C library functions from Smalltalk.
However, if you want to provide a more intimate link between C and Smalltalk,
as is the case with for example the GTK bindings, you should use the dynamic module
linking
system. This section explains what to do, taking the Digest
library as a guide.
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 Digest:
void gst_initModule(proxy) VMProxy *proxy; { vmProxy = proxy; vmProxy->defineCFunc ("MD5AllocOOP", MD5AllocOOP); vmProxy->defineCFunc ("MD5Update", md5_process_bytes); vmProxy->defineCFunc ("MD5Final", md5_finish_ctx); vmProxy->defineCFunc ("SHA1AllocOOP", SHA1AllocOOP); vmProxy->defineCFunc ("SHA1Update", sha1_process_bytes); vmProxy->defineCFunc ("SHA1Final", sha1_finish_ctx); }
Note that the defineCFunc
function is called through a function
pointer in gst_initModule
, and that the value of its parameter
is saved in order to use it 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 some17 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 gst_interpreter_proxy
variable.
Modules are shared libraries; the default directory in which modules
are searched for is stored in a gnu-smalltalk.pc file that is
installed by GNU Smalltalk so that it can be used with pkg-config
.
An Autoconf macro AM_PATH_GST
is also installed that will put the
directory in the gstmoduledir
Autoconf substitution. When using
GNU Automake and Libtool, you can then build modules by including
something like this in Makefile.am:
gstmodule_LTLIBRARIES = libdigest.la libdigest_la_LDFLAGS = -module -no-undefined ... more flags ... libdigest_la_SOURCES = ... your source files ...
While you can use DLD class>>#addModule:
to link a module into
the virtual machine at run time, usually bindings that require a module
are complex enough to be packaged as .star files. In this case,
you will have to add the name of the module in a package file
(see Packages). In this case, the relevant entry in the file will be
<package> <name>Digest</name> <filein>digest.st</filein> <filein>md5.st</filein> <filein>sha1.st</filein> <module>digest</module> <test> <sunit>MD5Test SHA1Test</sunit> <filein>mdtests.st</filein> </test> </package>
There is also a third case, in which the bindings are a mixture of code written specially for GNU Smalltalk, and the normal C library. In this case, you can use a combination of dynamic shared libraries and dynamic modules.
To do this, you can specify both <library>
and <module>
tags
in the package.xml file; alternatively, the following functions
allow you to call DLD class>>#addLibrary:
from within a module.
Open the library pointed to by with filename (which need not include an extension), and invoke gst_initModule if it is found in the library. If module is false, add the file to the list of libraries that Smalltalk searches for external symbols.
Return true if the library was found.
Add dir at the beginning of the search path of dlOpen
.
Save the current value of the search path for dlOpen
. This can be
used to temporarily add the search path for the libraries added by a
module, without affecting subsequent libraries manually opened with the
DLD
class.
Restore the last saved value of the search path.
Next: C callout, Up: C and Smalltalk