Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Preload DLL

169 views
Skip to first unread message

Christian Gollwitzer

unread,
Feb 5, 2016, 3:16:52 AM2/5/16
to
Hi all,

I'm using an extension (on Linux) which is dynamically linked to two
other libraries. This other libraries reside in nonstandard paths (it's
kind of a device driver). It would be nice to set the path to this
driver from within Tcl before loading the extension. setting
env(LD_LIBRARY_PATH) or env(LD_PRELOAD) did not change anything. I
vaguely remember that there was a way to make Tcl load any shared object
even if it has no _Init() function. I think that if I loaded the driver
library before the extension, that it should work, but I couldn't
succeed so far.

Thanks,

Christian

Georgios Petasis

unread,
Feb 5, 2016, 6:04:54 AM2/5/16
to Christian Gollwitzer
From the C level you can use Tcl_LoadFile:
http://docs.activestate.com/activetcl/8.6/tcl/TclLib/Load.htm

Tcl_LoadHandle handle;
Tcl_LoadFile(interp, path_obj, NULL, 0, NULL, &handle)

George

undro...@gmail.com

unread,
Feb 5, 2016, 6:08:20 AM2/5/16
to
Am Freitag, 5. Februar 2016 09:16:52 UTC+1 schrieb Christian Gollwitzer:

> ... setting env(LD_LIBRARY_PATH) or env(LD_PRELOAD) did not change anything.

you should have LD_PRELOAD point to the shared object (with absolute path)
*before* executing tclsh or wish. If all its external symbols can be resolved
it will be loaded already when main() of tclsh or wish gets called.

HTH,
Christian

koloska

unread,
Feb 5, 2016, 6:14:39 AM2/5/16
to
Maybe Ffidl http://wiki.tcl.tk/1197 can help to directly load the library?

For the record: On Windows a similiar problem can be solved by setting the working directory to the path where the additional libraries are situated. Is use this to load a library that needs some system libraries, that I copied just where the tcl package is. Then the following change to the pkgIndex.tcl works fine:

if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded zmq 4.0.1 [list ::apply {dir {
source [file join $dir critcl-rt.tcl]
set path [file join $dir [::critcl::runtime::MapPlatform]]
set ext [info sharedlibextension]
set lib [file join $path "zmq$ext"]
;# to load win32 libs, we have to switch the cwd
set cwd [pwd]; cd $path
load $lib Zmq
::critcl::runtime::Fetch $dir zmq_helper.tcl
cd $cwd; unset cwd
package provide zmq 4.0.1
}} $dir]

I have only added the cd commands.

Luckily (but unfortunately for you) on linux it's not as easy to fool the dynamic linker.

Christian Gollwitzer

unread,
Feb 6, 2016, 4:19:44 AM2/6/16
to
Am 05.02.16 um 12:08 schrieb undro...@gmail.com:
Well it works, of course, if I set LD_LIBRARY_PATH or LD_PRELOAD from
outside wish. However this requires a special startup file for any
script which makes use of the package. It would be ideal, if on package
require time, the pkgIndex.tcl could figure out the correct library path
and load the drivers before the binary extension.

I vaguely remembered some trick like "catch {load somelib.so}" would in
any case load the library, and even when this fails to initialize, leave
the library loaded to be available from the C side. Maybe I should try
it again with "load -global". Alternatively I'll also try to do static
linking of the driver library into the extension, but sofar couldn't get
this working.


Christian

Donald Arseneau

unread,
May 21, 2016, 1:00:31 AM5/21/16
to
Christian Gollwitzer <auri...@gmx.de> writes:

> Am 05.02.16 um 12:08 schrieb undro...@gmail.com:
> > Am Freitag, 5. Februar 2016 09:16:52 UTC+1 schrieb Christian Gollwitzer:
> >
> >> ... setting env(LD_LIBRARY_PATH) or env(LD_PRELOAD) did not change anything.
> >
> > you should have LD_PRELOAD point to the shared object (with absolute path)
> > *before* executing tclsh or wish. If all its external symbols can be resolved
> > it will be loaded already when main() of tclsh or wish gets called.
>
> Well it works, of course, if I set LD_LIBRARY_PATH or LD_PRELOAD from outside
> wish. However this requires a special startup file for any script which makes
> use of the package.

Back to the old days of how to start a Tcl file:


#! /bin/bash
# The next line is executed by sh, not Tcl; set LD_LIBRARY_PATH locally: \
export LD_LIBRARY_PATH=/foo/bar
# The next line is executed by sh, not Tcl \
exec /usr/bin/tclsh "$0" "$@"
#
proc test { } {...


--
Donald Arseneau as...@triumf.ca

tombert

unread,
May 24, 2016, 5:39:24 PM5/24/16
to
Maybe you can do something like this - restart "myself" if the custom path is not found in the environment:

## add lib32/lib64 library search path to environment
if {$tcl_platform(platform) == "windows"} {
if {$tcl_platform(pointerSize) == 4} {
set libPath [file join [file dirname [file dirname [info nameofexecutable]]] share lib32]
} else {
set libPath [file join [file dirname [file dirname [info nameofexecutable]]] share lib64]
}
set found 0
foreach path [split $::env(PATH) ";"] {
set path [file normalize $path]
if {$path == $libPath} {set found 1}
}
if {!$found} {
append ::env(PATH) ";[file nativename $libPath]"
exec [info nameofexecutable] [info script] &
exit
}
}

<here do your normal code>
0 new messages