Stubs: A dynamic linking mechanism for Tcl, Tk and extensions.
Georgios Petasis enthuses, "For me stubs is simply a brilliant feature of tcl."
A stubs table is a statically-linked table of symbols. This table can be included into statically-linked libraries, and then, at runtime, initialized against a library that provides the actual implementations for the symbols. This provides an alternative to OS-provided dynamic linking of shared objects.
Basically the stub mechanism provides a cross-platform dynamic linking mechanism using tables of function pointers.
To see the differences take a look at the following which describes what happens when Tcl loads two different extensions.
There are two/three levels of stubs support.
Level 0 - The extension doesn't support stubs at all. On many platforms (but not all) this means it is bound to an exact version of Tcl, but it always means that you'll probably have to recompile your extension to upgrade for a new version of Tcl. - Lars H: Upgrade what? The extension or Tcl? (The latter is probably more annoying.) UKo: made the description more clear (additions are emphasized)
Level 1 - The extension is stubs-enabled, using the stubs mechanism to dynamically bind to the Tcl (and Tk and other) library so that it can be loaded by any version of interpreter that supports the required version of API. Many many extensions provide this level of support (e.g. TclUDP) and this is the minimum level of support required for an extension to be supported inside a starkit.
Level 2 - The extension is a stubs-source and exports its own stubs table. This allows other code to dynamically bind to it. This is only useful where an extension provides its own meaningful C API. While this is theoretically separate from whether it is stubs-enabled, it is normally the case that all stubs-sources are also enabled. Tk and memchan are examples of stubs-sources.
Perhaps Jean-Claude Wippler suggested it to Paul Duffin in 1999, and Paul and Jan Nijtmans, with whom Jean-Claude had also been discussing ideas, implemented it in 2000. Others involved in the first generation were ??? (backlinking details) ...
DKF: I certainly remember suggesting something like the mechanism we ended up with back before Paul produced his initial version, though his initial version was a lot more elegant...
Under Linux and similer Unixes, check with ldd. No Tcl or Tk library references should appear. For Windows, do the same with "dumpbin /dependents".
Well, one place is that development against a Tclkit/Starkit/Starpack environment, extensions that are not built using Stubs result in more difficulty. (Or is it actually that they cannot be used at all?)
Is all this stubs stuff necessary? Why does the build system have to be so difficult. Believe us: this is far less difficult than the alternative. Yes, libtool and autoconf are maddening, but there are things outside the Tcl world that demonstrate we don't have it so bad. DKF briefly defends stubs in a follow-up [L1 ] to a lengthy thread that itself touches several aspects of generation.
Helmut Giese notes that, even when compiler providers agree on object formats, they might still construct libraries in incompatible ways. In particular, under Windows, those who choose to work with gcc-based compilation might need to rebuild tclstub84.lib before Stubs-enabled extensions load correctly.
Georgios Petasis and Michael Schlenker observe that Stubs-less languages need "batteries included'', because reliance on version-specific extensions would otherwise be prohibitively onerous: "the C interface of these languages seems so primitive that you have to recompile everything each time a new version is out."
Phils take on stubs Stubs - Another explanation
KBK: "Even in version lockstep, stubs can be handy if only to keep all of your libraries following the same linkage conventions."
hat0 Please note that, in building a cross-platform stub-enabled extension, that Windows may require this modification to your C code's declaration:
- int Extension_Init(Tcl_Interp *interp) + int DLLEXPORT Extension_Init(Tcl_Interp *interp)
Without this, linking may fail in curious ways, with errors such like:
Cannot export ??_C@_03KBFG@Tcl?$AA@: symbol not found Cannot export ??_C@_03PFGM@?$CJ?3?5?$AA@: symbol not found Cannot export ??_C@_0BC@JJNH@?0?5actual?5version?5?$AA@: symbol not found