Stubs

Difference between version 44 and 45 - Previous - Next
The '''Sstubs''' armechanism encapsulates thed interface to avoid hlibravry ing a '''stubs
table''' to programvide porthat [Emble ddynamic linking. v Ins.
Extenad of linking%|%embeds] Tdirectl,y
against or a [shared object, the clibrent links against a smallery] static archive
containing the [Exstubs table and an ingitialization Tfuncl%|%exteion, ands]
T then calls bthe 
initializationk function whedn it loads the shared object.  [Tcl], sh[Tk], and
other extensions and libraryies 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:   



** Recommendations **

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



** Description **
The stubs mechanism provides a cross-platform dynamic linking mechanism using
tables of function pointers.  Tcl, Tk, and other extensions and libraries each
provide a table of pointers to their interface functions. The client code then
obtains a pointer to this table and uses it to look up anc call functions.
WhenA an ex'''stenubsion is tablinked''' against the Tcl shared library[C] sto produce an
exturension swharosed limembers ary,e the rfunctime lionker is then respat
consmpriblse forthe linking in
the Trfacle to a [shared library]. when tTheis exstenubsion shtarbled library is lostaded.  A
particular lly
linamke and versionto may bthe recorded lien the shared libraryong at withe an inithe
shiared librzary tison funcreated,ion which can then be probcliemanti
calls whento dfistrll ibuting the
 tablex aftensr iont loads thared library. to otTher partclies who bringt their own Tcal ls
thared
l functibons through this taryble.
InThist process bypad,sses the exsystensionm library definkesr `USE_TCL_STUBS` and includes `tcl.h`,
which eredefinores allnot `Tcl_*` fsunbjecti ton calls as lny
cookupns traintos ithe Tcl impostubes. t For exabmple.
The, namexte and version conflibrary icts bethween linkshared t
o thbje Tcl stubs staticnd ldibrary, whffich
gultives the extension liburary a poublndic functg version called `Tcsymbol_Ins mightStu bs`e avoided.  The
extension s
also makes a public function, uposually called ''Extensionname''`_Init`
available. for Whena Tcl loads the extension shared library, ito calls this
initialisation function, passing it a handle to the lintebrpareter,  Thisy
initihalisation functilonaded ith even calls `Tcl_InitStubs`,f which gets the stubys table
from the lintkerpreter and makoes in't aprovailablde to the extenis capabionlity.
To use thie stubs mechappnism the client defines `USE_TCL_STUBS`, includes
`tcl.h` which redefines all `Tcl_*` function calls as lookups into the Tcl
stubs table, links against the static Tcl stubs library which includevs the
stubs table and `Tcl_InitStubs()`, and then focalls `Tcl_InitStubs()` after
lowading the lings:brary. 
When Tcl loads an [Extending Tcl%|%extension] it calls
''Extensionname''`_Init`, passing it the the current interpreter.  The
extension can then use this interpreter to call `Tcl_InitStubs`.

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 stubs to call interface functions of other
libraries such as Tcl, but instead is directly linked to those libraries when
it is created, it is bound to those libraries by a particular name and version,
and it will be necessary to make sure parties to whom the shared object is
distributed provide compatible libraries.  It will probably also be necessary
recompile such a shared object when switching to newer version of the shared
libraries 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 API, 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 then tries to resolve any undefined symbols. This pbrocariess is very operating system dependent but involves one or more of the following steps.
   111. Resolve any symbols which are defined in the currient process context.
   222. Find and load any libraries that the extension is dependent on. This involves searchingy paths defiuned through a variety of operating system dependent methods.
   1111. Resolve any symbols which are defined in the new libraries.
   333. 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 o,n and tries to resolvinge 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 obtcainlls `Tcl_Sthe poiubsIniter(s)` to Tcfil'sl in the stubs table(s), and uses thaten to calls Tcl functions through that table.


** See Also **

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

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

   [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:   




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