Loading external libraries

From the Tcl chatroom on 2002-01-16 (on loading shared libraries that depend on other shared libraries):

suchenwi: I just discussed with the colleague who will do the Tcl+C part of our presentation tomorrow. He was disappointed that libs loaded with the package mechanism must be self-contained, i.e. not reference any other libs (except if those also implement (libname)_Init, but that's maybe not fair for libstdc++.so ...

tclguy: eh? That's not entirely correct. eg, incr Tk references incr Tcl. also, you can have other .sos dependent.

suchenwi: Is that because it's hard or impossible in Windows, this possibility was dropped on Linux too? (That's what he thought). But the only way he managed was to extract all objects, paste them into a huge, self-contained so.. then it worked.

lvirden: what kind of loading was he wanting?

tclguy: I'd need a more concrete example ...

suchenwi: After removing a call to std::cout. He followed the instructions in Welch 3rd ed.

tclguy: well, Welch never delved into that much complexity (it's hard without good use cases)

kennykb: Ah. Slightly strange issue. If you want to load a C++ library on some systems, you have to make sure that a C++ compiler compiled your main program. or rather, that a C++ linker linked it.

suchenwi: Load mechanism: create pkgIndex, package require. gcc 2.95.2 or so.. it has a g++ variant, but we're just beginning to switch to C++.

suchenwi: Kevin: right - I remember that linking has to be done with g++, not ln. But the bulk of our software is still in C, compiled with acc (or MSVC).

suchenwi: So his conclusion was, Tcl-enabled shared libs must take care of loading all the shared libs they depend on on their own, in the (libname)_Init function; while on Linux this could have been automatized by using the linker.

kennykb: Richard: Except for the problem of static initializers in C++ code, I routinely just let one .so or .dll refer to another. I have packages that are simply thin wrappers around other people's libraries.

suchenwi: I see. But if you have libfootcl.so, which has a footcl_Init, and requires libbar.so, which requires libgrill.so? Is libfootcl then responsible for loading bar and grill?

kennykb: It does it implicitly by having been linked with them. If I'm worried about the possibility of bar and grill being missing from the target system, I'll load them explicitly, so that the process won't abort if they are.

lvirden: Richard, at least on Solaris, I can specify, when creating a .so shared library, that there are additional dependencies on other libraries that get resolved at load time. I have just that situation with oratcl.

suchenwi: But it appeared as if Tcl's load mechanism tries to do the resolution, by calling the respective (libname)_Init function... but in vain.

lvirden: In my case, the extra libraries are not Tcl libraries, but other related libraries. Someone else is going to have to address the specifics of tcl libraries calling other tcl libraries.

kennykb: Tcl_PkgRequire from within the library, then use the package's Stub table...

suchenwi: Do other packages besides Tcl have stub tables? I first heard the term in that context. What he wants to do is e.g. load libtiff, libz, or stuff like that.

kennykb: Richard: I was answering Larry's question. TEA-compliant extensions with C API's have stub tables. Libtiff, he should just be able to link with.

tclguy: incr Tcl has a stubs table. But Img does what you want, without any extra stubs stuff. Look at that. btw, extensions do not require their own stubs tables. TEA-compliant extensions USE the tcl and/or tk stubs tables.

aku: Ok, libraries loading other libraries:

1) Tcl library requiring another Tcl library. Do 'package require' or the c-level equivalent to perform searching, loading and initialization

2) Tcl library requiring non-tcl library

a) Link the tcl library against the other libraries and the OS will load them as necessary. Example OraTcl

b) Plugin architecture, or no fixed library for a given functionality. Use dlopen, etc. to load the other libraries on-demand. Examples: Trf, TrfCrypt, Img.

Regarding (2b) Jan Nijtmans proposed to expose platform independent interfaces to dlopen, dlsym, dlclose as part of the public api so that extensions like trf, img, etc. do not have to carry duplicate code around. Anyone caring enough to write up a TIP for this ?

LV: other information on this. In the case lvirden (that's me) mentions above, when I build Oratcl out of the box, I get an unresolved symbol error because the libraries chosen on my hw/sw/versions/whatever combo end up not seeing one of the specific oracle libraries. To get around this sort of problem, and perhaps the problems Richard is mentioning, on Linux and Solaris you use the -R flag in the link step. Basically, the -R flag takes as an argument one or more directories (seperated by :) which will contain dynamic libraries when the extension or application is accessed during run time. The runtime support code then walks through all the supplied directories, looking for the first occurence of the needed library, without the application having to do anything specific.

Another case that doesn't have a good answer is when you depend on an external (non-Tcl) library *and* you're distributing via a starpack. I don't know of any good way to do this.