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

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 LDFLAGS2. 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 Blox 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 add the name of the module in the packages.xml file. In this case, the relevant entry in that file will be

     <package>
       <name>BloxTK</name>
       <namespace>BLOX</namespace>
       <filein>BloxBasic.st</filein>
       <filein>BloxWidgets.st</filein>
       <filein>BloxText.st</filein>
       <filein>BloxCanvas.st</filein>
       <filein>BloxExtend.st</filein>
       <filein>Blox.st</filein>
       <module>blox-tk</module>
       <directory>blox-tk</directory>
     
       <file>Blox.st</file>
       <file>BloxBasic.st</file>
       <file>BloxWidgets.st</file>
       <file>BloxText.st</file>
       <file>BloxCanvas.st</file>
       <file>BloxExtend.st</file>
       <file>colors.txt</file>
     </package>

Footnotes

[1] The most notable are aix and Windows.

[2] Specifying -no-undefined is not necessary, but it does perform that the portability conditions explained above (no reference to symbols in the virtual machine) are satisfied