Next: , Up: C and Smalltalk  


5.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 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.

Function: mst_Boolean dlOpen (void *filename, int 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.

Function: void dlAddSearchDir (const char *dir)

Add dir at the beginning of the search path of dlOpen.

Function: void dlPushSearchPath (void)

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.

Function: void dlPopSearchPath (void)

Restore the last saved value of the search path.


Footnotes

(17)

The most notable are AIX and Windows.


Next: , Up: C and Smalltalk