Updated 2017-12-09 13:46:03 by EF

load dynamically links a code library (typically written in C, C++, or some comparable language) with the program containing the Tcl interpreter. Most [extensions] use this mechanism.

See Also  edit

Tcl Extension: User Guide
dlopen extension
a small extension to open shared libraries that aren't Tcl extensions. This is available at http://www.noucorp.com/Tcl/utilities.
ffidl
twapi
tcom / COMet
Tcl_InitStubs
info loaded
info sharedlibextension

Synopsis  edit

load fileName ?packageName? ?interp?

Documentation  edit

official reference
official reference: C API

Description  edit

If fileName does not contain any directory separators, the file will be searched for in OS-specific ways. If packageName is not provided, it is derived from the fileName by trimming certain prefixes and suffixes and applying capitalization rules (so /usr/local/lib/libfoobar.so would become Foobar); it is used to locate the name of the initialization function inside the library. If interp is not supplied, the library is initialized for the current interpreter.

On Microsoft Windows, attempting to load a .dll file for which Read & execute permissions are not allowed results in an error:
couldn't load library ".../some.dll": permission denied

Troubleshooting  edit

So what do you do when load, or, even more mysteriously, package, fails? There are many, many ways for this to happen, and typical built-in diagnostics from supplied loaders are inscrutable.

One handy tool for such situations is a dependency utility. Under Windows, DependencyWalker [1] walks dependencies. When you let it load a specific dll, it assists you in determining what other DLLs it needs.

AMG: I just had a very strange problem with load. When I screw up and try to call my command without loading the the package first, of course I get an error for the command, but I also get an error when trying to load the package. When I do things in the right order, everything works. Yeah I know, I shouldn't be trying to do things backwards, but I still wonder why the load fails.
[andy@toaster|~/e6b]$ tclsh
% atc::get_dnlink
invalid command name "atc::get_dnlink"
% load atc.so
couldn't load file "atc.so": atc.so: cannot open shared object file: No such file or directory
[andy@toaster|~/e6b]$ tclsh
% load atc.so
% atc::get_dnlink ABCD
conversion failed
% info patchlevel
8.6b2
% exec uname -a
Linux toaster 3.4.0-andy #2 Fri Jun 1 23:52:05 CDT 2012 i686 Pentium II (Deschutes) GenuineIntel GNU/Linux

Just so you know, that "conversion failed" message is the right result.

This library is not stubs-enabled. It also does not link against -ltcl8.6. Update: linking against -ltcl8.6 doesn't help; this error still happens.

I'd file a bug report, but the above is all the information I have at the moment. It seems like more is needed, yet I don't currently have any time to research further.

Update: here's another rather interesting failure mode:
[andy@toaster|~/e6b]$ tclsh
% load per.so
% per::get_integer ABCD 0 4
10
% load atc.so
couldn't load file "atc.so": atc.so: cannot open shared object file: No such file or directory
[andy@toaster|~/e6b]$ tclsh
% load atc.so
% load per.so
couldn't load file "per.so": per.so: cannot open shared object file: No such file or directory

Even when the first command doesn't result in an error, if the second or subsequent command is a [load], it fails. This makes it impossible to load more than one library.

The next step for me is to build the very latest Tcl and see if the problem persists.

Update 2: I just built the most recent trunk (1581f9beac5715890d105a41090756a89b0f3630 2012-06-15 09:39:34 UTC), but the problem persists, exactly the same as before. The system is running Slackware 13.1, if that helps. I might be able to fiddle around in gdb if anyone can point me toward something I ought to be looking at.

Update 3: This is only a problem for interactive use. Everything works fine when [load] is called from a script.

DKF: If you've omitted the return TCL_OK; at the end of the Init function (a bug in the code above that I just corrected), the result code will be a bit random (it'll depend on whatever happens to be in the relevant register!) and in your case that's causing this weirdness. No idea why that triggers in the precise failure mode you describe (I'd have to disassemble the init function to figure out, and possibly a few other things too!) nor do I care to dig further. Note that you should have been getting warnings about failing to return a value from a non-void function; those sorts of warnings are highly relevant, and indeed ought to always be errors…

HaO 2015-07-01: To load a DLL on windows might require a special placement of the library.

To make a long story over TCL and Windows Hotfixes short: if you have an experience as follows:
% load test.dll
couldn't load library "test.dll": this library or a dependent library could not be found in library path

The reasons might be:

  • The dll is not in the same path as you wish interpreter exe or in the Windows system places for DLL's (c:\windows...)
  • You have specified a relative path ("./test.dll")
  • Your dll has dependencies to other dll's which are not loadable -> use "dependency walker" to check
  • Your dll name is not identical to the Init symbol -> specify it: "load test.dll OtherName"

VFS and starkit  edit

Usually, when loading from a virtual filesystem, e.g. starkit, load will function as advertised. In practice, the dynamic library is temporarily extracted out of the virtual filesystem and copied into a temporary folder on the local disk. This will however not work if the library itself depends on other dynamic libraries (typically placed in the same directory). See Caching Dynamic Libraries and Fixing Dependencies for a solution. EF