Hi Jeff,

I'm pretty sure stubs aren't the problem since neither BLT nor the perl Tcl module are compiled against the stub libraries. They are compiled against exactly the same version of libtcl8.4.so.

When I examine the perl Tcl module library, I see a dependence on libtcl8.4.so:

ldd <blah>/perl/5.8.2/lib/site_perl/5.8.2/i686-linux-thread-multi/auto/Tcl/Tcl.so
       libtcl8.4.so => <blah>/tcl/8.4/lib/libtcl8.4.so (0x00b62000)
       libc.so.6 => /lib/tls/libc.so.6 (0x00577000)
       libdl.so.2 => /lib/libdl.so.2 (0x00e83000)
       libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00708000)
       libm.so.6 => /lib/tls/libm.so.6 (0x00144000)
       /lib/ld-linux.so.2 (0x00785000)

So as I understand it, when perl loads Tcl.so, that should force the dynamic loader to also load libtcl8.4.so. When I look at our BLT library:

ldd <blah>/tcl/8.4/lib/libBLT24.so
       libc.so.6 => /lib/tls/libc.so.6 (0x0050d000)
       /lib/ld-linux.so.2 (0x00785000)

It does not show any dependence on libtcl8.4.so (but I am certain that this is the version of Tcl against which it was compiled).

However, when perl tries to load BLT inside the Tcl module, there are unresolved symbols. This script:

#!<blah>/perl/5.8.2/bin/perl
use Tcl::Tk;
my $m = Tcl::Tk::MainWindow->new();
my $i = $m->interp();
$i->Eval('package require BLT');

gives this error:

ERROR: couldn't load file "<blah>/tcl/8.4/lib/libBLT24.so":
<blah>/tcl/8.4/lib/libBLT24.so: undefined symbol: TclpRealloc

If I use just Tcl rather than Tcl::Tk I get the same error. The missing symbol TclpRealloc is found in libtcl8.4.so:

nm <blah>/tcl/8.4/lib/libtcl8.4.so | grep TclpRealloc
0007ade8 T TclpRealloc

So my conclusion is that libBLT24.so needs to have libtcl8.4.so loaded even though it doesn't ask for it explicitly. Perl should be loading libtcl8.4.so since it is asked for by perl's Tcl.so. However, for some reason when I "use Tcl" from perl, libtcl8.4.so does not get loaded, and hence it is not there when libBLT24.so needs it.

I think this confirmed by the fact that everything works if I force the loading of libtcl8.4.so like so:

#!<blah>/perl/5.8.2/bin/perl
use Tcl::Tk;
my $m = Tcl::Tk::MainWindow->new();
my $i = $m->interp();
$i->Eval('load /usr/csite/pubtools/tcl/8.4/lib/libtcl8.4.so Tcl');
$i->Eval('package require BLT');

Then I get no error. What I don't understand is why I have to do that. Perl should be loading libtcl8.4.so automatically, but for some reason it doesn't.

Is there any way to get perl to tell me exactly what libraries have been loaded? In Tcl I would use "info loaded" for this purpose.

--Brian

Jeff Hobbs wrote:
Hi Brian,

This is a dangerous path on several levels. If the libtcl.so you load isn't the exact same one used by Tcl::Tk, you can have all sorts of conflicting library issues. The issue that you are hitting is regarding Tcl's stubs mechanism. This is the mechanism that provides a high level of binary version independent, but also enables the single-file dll/executable features of Tcl. More about stubs at:

http://wiki.tcl.tk/285

BLT, while a nice fancy widget package, is well known to not support the stubs interface (in large part because it pokes deeply into Tcl/Tk internals, which mostly aren't exposed by stubs). If you are using a Tcl/Tk through Tcl::Tk that isn't a single-file dll (such as the one shipped in ActivePerl for user convenience), then you should be OK, as long as you compile BLT against that Tcl/Tk.

Let me know if you have any more questions on that.

Regards,

Jeff

Brian Bevins wrote:
Vadim and Jeff,

I am a colleague of Michele's here at Jefferson Lab. I built the versions of Tcl and Tcl::Tk that she is having trouble with. Thank you for responding so promptly to our questions.

Our initial build of Tcl:Tk 0.97 failed because our version of Perl (5.8.2) has an Exporter that lacks the import method. That method was introduced with the Exporter that shipped with Perl 5.8.3. I had to go back to Tcl::Tk 0.91 to find a version that did not require the Exporter->import() method. That one built just fine and passed all its tests. We can use this until our sysadmins give us a new version of Perl.

The problem loading BLT under Tcl or Tcl::Tk is completely separate. It seems that both libblt24.so and libbltlite24.so depend on symbols from libtcl8.4.so. As built out of the box, the BLT libraries do not explicitly force the Tcl library to be loaded. They seem to expect that Tcl will already be loaded. Normally this is the case and BLT works fine when used directly from tclsh or wish, but for some reason under Tcl and Tcl::Tk this is not the case.

When I look at the Tcl.so library for Perl, it does indicate an explicit dependency on libtcl8.4.so. But for some reason "use Tcl" (or "use Tcl::Tk") does not force libtcl8.4.so to load. I have worked around this in Perl for the time being by loading it explicitly as:

use Tcl::Tk;
my $m = Tcl::Tk::MainWindow->new();
my $i = $m->interp();
$i->Eval('load /usr/csite/pubtools/tcl/8.4/lib/libtcl8.4.so Tcl');
$i->Eval('package require BLT; blt::tabnotebook .bltnbook1; pack .bltnbook1');
$i->MainLoop();

This makes it work, but I do not know why the explicit load command is necessary. The dynamic loader should be doing that for me.

Many thanks,
--Brian


--
Brian S. Bevins, PE
Computer Scientist / Mechanical Engineer
Thomas Jefferson National Accelerator Facility

    "Nothing in all the world is more dangerous than
     sincere ignorance and conscientious stupidity."
                                    --Martin Luther King Jr.







Reply via email to