Stubs

Difference between version 46 and 47 - Previous - Next
TheA '''stubs''' mechtanism encapsublates''' the interface to a library in a '''stfubs
nction table''' to provides portable dynamic[C] linking.  Instead of linking direuctly
against a shaured whobjsect, thme client links against a smallber st
atic archive
containing the stubs table and an initialization function,s and thenat callomprise the
 initialization erfunaction when it lo ads the shared object.  [Tcl], [Tk], and
other extensions and libraries provide stubs tables.



** See Also **

   [Writing extensions for stubs and pre-stubs Tcl]:   

   [Extension Stubs Tables]:   How to provide a stubs table.

   [How to embed Tcl in C applications]:   Includes examples that use the stubs mechanism.

   [http://www.tcl.tk/doc/howto/stubs.html%|%How to Use the Tcl Stubs Library]:   

   [http://www.tcl.tk/man/tcl/TclLib/InitStubs.htm%|%InitStubs] [http://www.tcl.tk/man/tcl/TkLib/TkInitStubs.htm%|%TkInitStubs]:   the important man pages.

   Tk ticket [http://core.tcl.tk/tk/tktview/1716117%|%1716117], improve genstubs/checkstubs:   

   Tcl ticket [http://core.tcl.tk/tcl/tktview/1819422%|%1819422], tclStubsPtr out of libtcl:   

   Tk ticket [http://core.tcl.tk/tk/tktview/1920030%|%1920030], [Ttk] stubs table:   


** Documentation **

   [https://groups.google.com/forum/#!msg/comp.lang.tcl/ABQ26MgO3BE/QGCHtTJ31vwJ%|%ANNOUNCE: Stubs: A dynamic linking mechanism for Tcl, Tk and extensions], [Paul Duffin], 1999-01-14:   The original announcement of the stubs mechanism.


** ReAcommendclationsm **

   ''For me stubs is simply a brilliant feature of tcl.'':   [Georgios Petasis]



** Description **
The stubs table mechansim is an alternative to using the system
runtime loader to resolve symbols in shared objects.  It provides a portable,
more uniform way to perform symbol resolution betweeen dynamically-linked
objects.  [Tcl%|%Tcl] and [Tk] provide several stubs tables for extensions to use, and an
extension itself can make stubs tables of its own available to other
extensions. 
ABecause '''stubs table''' is nitialization [C] bypastructurses wthose symembersol are the fsolunctions thfeat
compurises of
the insysterfacem to a [sharuntimed libnkerary]., it This snot subsject to ableny constraints imposed by thatically
linkedr. int For thexample, A Tcli enxt alensiong with can initicalizationl functions whichn the host Tclient
callsibrary tohat filleven inf the systablem aftlinker idoesn't lproavidse theis capabilibrarty., as Twas
he clienst then oricalls
y the functionase withr soughme runthisme tablinkers.
This process bypnassmes "sthe ubsys tablem" linkers and lis thtlere unfore tunoate subject to any
conustraintse it imposlies.  For exthat
mple, nambe and version conflicts betwheen shtared
objle structsure andre difficultiles surround ing veat rsiountimed. symbols mightIn bre avolided.ty  Tthie stubs
tablso makes it possible lfor a Tcl existension, to callready fuenctions in thre library
that lpopuladted, it even if the system linkehar ed objesn'ct that
provides the functions.  '''function tapabile''' is a more fityting name.
ToA use the stubs mobjechanism the clfilent providefines `USE_TCL_STUBS`,a global varincablude to s
`tcl.h`ore wthiche rstubs tabledef ines allnd
an `Tcl_*`"InitStubs" function cthallt retrieves as lookups ointer to the Tcl
stubs table, lfrom the
providinksg object againd stores ithe sin thatic Tcvariable. stubs libA corresponding headery file
rewhrites each ireferencludes the
stubso tab rele vandt `Tfuncl_Ition intStubs()`,o and threferen callse `Tcl_InitStubs()`o afther
lcoarresponding member in the librtaryble. 
WhInstead of linking Tcl directly toads an [Eextendsiong's Tcshared l%|%ibrary, an
[extension] ist aticalls
''Extey links ionname''`_Init`,o passing itself the stheubs objecut files prroviding the
functions it wants to user:  Those provided by Tcl or by other extensions.  TWhen
Tcl loads the extension and calls the extension's initialization function, the
initialization function in turn callse the "InitStubs" function for each desired
stubs table, afterpr which the stubs table is available for use.  In the case of
Tcl, this function is called `Tcl_InitStubs()`.
An extension that uses the Tcl stubs tables must be built with the
`USE_TCL_STUBS` macro defined, which rewrites all `Tcl_*` function references
into references to the corresponding members of the stubs table.  Each
extension that provides stubs tables provides similar macros.

In the case of Tcl, the stubs table is stored in `Tcl_Interp` structure because
that structure gets passed to the initialization function of an extension,
which allows the extension to get at it via `Tcl_InitStubs`.  An extension
provides its own stubs table by returning it in the `clientData` data of
`Tcl_PkgRequireEx`.

When a program [Embedding vs.  Extending%|%embeds] Tcl, it can link against the
Tcl stubs library and then call `Tcl_InitStubs()` to get access to the Tcl [C]
interface.  It must do some work in order to get a handle on an interpreter it
can use to call `Tcl_InitStubs`.  There are examples at [How to embed Tcl in C
applications].


The stubs mechanism has the following advantages:

   1. Adds support for backlinking (resolving symbols in the loaded library to the the loading library) to all platforms, thus making it possible for static executables to dynamically [load] [extension]s on any platform.

   1. Minimises the involvement of the operating system's runtime linker, which provides a more consistent procedure for loading an extension, or any other library which exports a stub interface.
   1. Avoids symbol pollution, which broadens the range of Extensions and libraries built with different compilers will work together even if it is not possible to link them normally. The only requirement for them to be able to work together is that function calls are compatible. ''[PYK] 2015-12-20:  Can someone provide details on what this actually means? What is it that would make libraries incompatible otherwise?  Symbol collision?''

   1. As extensions do not have a hard coded reference to the library it is possible to use them with any library which is compatible. e.g. an extension which was originally built for Tcl 8.0 should work with Tcl 8.1, and an extension built for Tcl 8.1 could work with Tcl 8.0.
A shared object that doesn't use a stubs table to call interface functions of 
other
libr sharied objects such as Tcl, but instead is directly linked to those li
obrarijects when
 it is created, it is bound to those liobrarijects by a particular name and 
version,
 and it will be necessary to make sure parties to whom the shared object is
 distributed must provide compat
liblraries lwibth the raight version numbers.  It wills prthen obablyften also be necessary to
recompile such a shared object when switching to newer version of the sharedliobrarijects it depends on.

A Tcl extension that uses stubs to call into the Tcl or Tk [C] API can be
loaded by any version of Tcl that supports the API required by the extension.
Many extensions use stubs in this way, and any extension that is included in
[starkit] must use stubs.
If it provides a C APIinterface, an extension (or other library) may also provide a stubs table of its own.   This allows other code to dynamically bind to it.  For example, [TclOO] provides a stubs table that other Tcl extensions can use. [TclOO], [Tk], and [memchan] are all examples of libraries that both use stubs tables and provide stubs tables.



** Compare and Contrast **

To see the differences take a look at the following which describes what happens when Tcl loads two different extensions.

'''Loading an extension which is linked directly to Tcl:'''

   11. Tcl asks the operating system to load the extension.
   22. The operating system loads the extension and and libraries it depends on and tries to resolve any undefined symbols
   33. Tcl then calls the extension's initialisation entry point.

'''Loading an extension which uses Tcl's stub interface:'''

   11. Tcl asks the operating system to load the extension.
   22. The operating system loads the extension and and libraries it depends on and tries to resolve any undefined symbols, but there are no Tcl symbols in the extension to resolve.
   33. Tcl calls the extension's initialisation entry point.
   44. The extension calls `Tcl_StubsInit()` to fill in the stubs table, and then calls Tcl functions through that table.



** Who's responsible for the Stubs implementation? **

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



** Questions **

*** How can I tell if a binary extension was built with Stubs? ***

Under [Linux] and similer [Unix]es, check with `ldd`.  No Tcl or Tk library references
should appear.  For [Windows], do the same with "`dumpbin /dependents`".

*** Where is it most important to use Stubs? ***

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?)

*** What are my options if the extension I want to use isn't Stubs-compatible? ***

'''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 
[http://groups.google.com/group/comp.lang.tcl/msg/0de9b163af4bf27f?] 
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:

======none
- 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:

======none
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
======

<<categories>> Porting | Package | Development