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

Problems with extension stub libraries

95 views
Skip to first unread message

Matthew Swift

unread,
May 9, 2002, 8:18:02 AM5/9/02
to
I've recently written a Tcl 8.2 extension that has its own stub
library. This contains a single function definition (much like the Tcl
stub library) that is used to initialize its stub table pointer:

/* global stub pointer*/
MdXmlaStubs *mdXmlaStubsPtr;


/* MDXMLA_InitStubs: initialize stub vector */
const char *
MDXMLA_InitStubs(
Tcl_Interp *interp,
char *version,
int exact
)
{
...

actual_version = Tcl_PkgRequireEx(interp, "mdXmla", version,
exact,
&client_data);

...

mdXmlaStubsPtr = (MdXmlaStubs*) client_data;

...
}


So far I've been building the stub library with the "USE_TCL_STUBS"
macro defined causing the call to "Tcl_PkgRequireEx" to go indirectly
via Tcl's stub table.

Everything works fine where my Tcl extension is used by other
extensions: they link against the Tcl stub library and my stub
library.

However, I've run into problems on Windows when I try to link against
the extension's stub library from Tcl applications. The reference to
Tcl_PkgRequireEx via the stub table fails because, it seems, the Tcl
dynamic library does not contain a definition of tclStubsPtr. It's
there on UNIX in libtcl8.2.so - this library includes tclStubLib.c.

So was I wrong to assume that libtcl8.2.so and tcl82.dll would have
their own tclStubsPtr defined? I have several options:

1) Link the main application against tcl82.dll and the associated Tcl
stub library to make sure I have a definition of tclStubsPtr.

2) Build two versions of my extension's stub library: the first is
built with USE_TCL_STUBS defined, the second without. Other extensions
link against the first, applications link against the second.

Neither solution feels right to me. Am I doing things wrong? Or have
things change recently that facilitate this kind of thing (at the
moment we're using Tcl 8.2 but we're planning to upgrade to 8.3.4).

I performed a quick search on the newsgroup to see if I could find
anything related. All I came up with was this thread containing a post
from David Gravereaux. It doesn't fill me with much confidence, but it
was a while ago so things may have changed since:

http://groups.google.com/groups?hl=en&selm=37b1d995.244865317%40news.maui.net&rnum=7

> Add on to that, the problem of the "level 2 Tcl_PkgRequire circularity
> thing" for custom Stubs tables and I've come to the conclusion that
> distributing a <pkg>stubs.lib is a total waste. You will just always
> need the source of the module you are building against to make that
> custom <pkg>stubs.lib fit your needs... for that specific compile...
> you're doing right then.

Thanks,

Matt

David Gravereaux

unread,
May 9, 2002, 9:30:47 AM5/9/02
to
matthe...@messagingdirect.com (Matthew Swift) wrote:

>So was I wrong to assume that libtcl8.2.so and tcl82.dll would have
>their own tclStubsPtr defined? I have several options:

I get so confused by Stubs, but think it's the coolest thing.

1) tclStubsPtr is declared in tclDecls.h included from tcl.h.
2) tclStubsPtr is defined during the link with (on win) tclstub8X.lib.
3) Is really located in your dependant, not the core, from the Stubs library.

If you're defining USE_TCL_STUBS for compiling your stubs table, including
tcl.h, and linking the resultant with tclstub8X.lib, there shouldn't be an
error. When built for static and linking into an app, replace
MDXMLA_InitStubs() with a simple Tcl_PkgRequire instead. And MDXMLA_InitStubs()
should be in a separate library from the extension itself. The core has it in
it, just because it's at the bottom of the feeding chain (or similar).

The [Incr Tcl] project might help by looking at what it is doing. Or, how [Incr
Tk] is making use of Itcl through Stubs.

There's many ways to fall on ones face with Stubs. It's an delicate balancing
act sometimes.
--
David Gravereaux <davy...@pobox.com>
[species: human; planet: earth,milkyway,alpha sector]
Please be aware of the 7.5 year ping times when placing a call from alpha centari

Jean-Claude Wippler

unread,
May 9, 2002, 1:16:17 PM5/9/02
to
David Gravereaux <davy...@pobox.com> wrote:

> matthe...@messagingdirect.com (Matthew Swift) wrote:
>
> >So was I wrong to assume that libtcl8.2.so and tcl82.dll would have
> >their own tclStubsPtr defined? I have several options:
>
> I get so confused by Stubs, but think it's the coolest thing.
>
> 1) tclStubsPtr is declared in tclDecls.h included from tcl.h.
> 2) tclStubsPtr is defined during the link with (on win) tclstub8X.lib.
> 3) Is really located in your dependant, not the core, from the Stubs
> library.

[...]


> There's many ways to fall on ones face with Stubs. It's an delicate
> balancing act sometimes.

(Maybe it's time to make stubs the default in tcl.h?)

I'm not sure I understand the issues Matt is raising. But let me try to
explain why stubs are worthwhile, and also simpler than they look <wink>.
My apologies if I'm stating the obvious...

In the non-stubbified world, when an extension is loaded, it uses the
system linker to resolve references to the Tcl runtime (libtclX.Y.so or
tclXY.dll). If you want to build a second-level extension which uses
both, then you need to resolve against both.

Trouble is, all of this creates dependencies, which on several os'es
require either paths built into the extension, or some sort of path
environment variable so the system can roam around the entire disk to
find the relevant shared libs. Worst of all, an extension built for Tcl
X.Y will not work with anything *but* libtclX.Y.so and tclXY.dll, even
if the APIs are still perfectly compatible.

Stubs can side-step it all. The Tcl runtime locates the extension and
loads it, and essentially hands it a vector of callbacks. So no matter
how the extension is called, it knows how to call things in the runtime
(and can in fact be used by N different runtimes, even concurrently).
The point is that the extension has *no* linkage at all to Tcl. Instead
it loads a little bit of object code (statically!) that replaces all the
Tcl calls with fake calls through the passed-in stub vector. To make
that work, the extension must init the stubs mechanism, which consists
of stashing the stub vector pointer in a global, so the fake calls know
where to call. I won't go into the fact that the fake code is actually
replaced by macro's - that's merley an optimization.

This is a very normal and simple mechanism, C++ vtables and Win32 COM do
exactly the same. One could call stubs an equivalent of "late binding".

Things could be simplified in Tcl. For one, one has to keep in mind
that libtclstubX.Y.a and libtclX.Y.so are mutually exclusive. Either
you use stubs, define USE_TCL_STUBS, and link with libtclstubX.Y.a, or
you don't, and then you will have undefineds that need to be resolved
with dynamic linkage.

Note that there is no such thing as a "libtclstubX.Y.so".

IMO, it would have been a *lot* less confusing if we had not called the
fake stubs a stub *library*, i.e. libtclstubX.Y.a, but libtclstubX.Y.o
(a one letter difference: it's not a lib at all, it's a bit of support
code to make the fake stuff work). Actually, I'd name it libtclstub8.o,
because that little bit of startup code in fact won't change at all.

It would have been even simpler, if that little bit of fake startup code
had not been compiled but placed in the header, either tcl.h or some new
name. Because stubs really replace a compiler/link/run-time mechanism
by something that needs nearly no code to work.

The impact becomes clear when you consider that Tcl is a scripting core,
and that header files and stub libs are meaningless for all but those
developers which develop compiled extensions. The current approach
needs a working Tcl system, but also headers and the libtclstubX.Y.a
"library" to be able to compile an extension. I've run *numerous* times
into the need to compile an extension, but finding out that the Tcl
setup did not have the required matching headers and libs. The irony is
that *any* set of headers plus libtclstubX.Y.a would have sufficed: due
to the fact that Tcl maintains forward compatibility, there is no need
at all to update the headers or stub lib, as new Tcl cores are installed.

To get back to the issue of creating an extension "foo" which uses stubs
in the way at least *one* person intended them to be <wink>, do:
- always define USE_TCL_STUBS and link to libtclstubX.Y.a
- define a stub vector for foo, and compile foo *without*
the define "USE_FOO_STUBS"
- build libfoostub.a with fake startup for the foo vector
- extension bar can then use extension foo and tcl, if it
defines both USE_TCL_STUBS and USE_FOO_STUBS, and links
to both libtclstubX.Y.a and libfoostub.a

To summarize this long story: stick to the above and IMO you won't have
to fight the stub design as much. The most common mistake I come across
is people still linking with -ltcl8.?, which works fine until they have
a case where stubs are needed. The thing to check with extensions, is
that "ldd" does *not* point to a tcl runtime shared lib (on win32 there
are tools such as depend.exe to do the same).

For the TCT, I'd like to summarize with a few "requests for change",
knowing that some of these suggestion may be too late to get in there:
- EITHER: drop libtclstub8.5.a, and generate libtclstub8.o instead
- OR: distribute the "tclStubLib.c" instead, perhaps as "tclstub.h"
- make "USE_TCL_STUBS" the default
- state that linking with "-ltcl8.5" is bad, except for main apps

<plug>

If you find all of this clear as mud and you need to write C code that
is to be used as Tcl extension, there is also the CriTcl ("C runtime in
Tcl") package, which carries tcl.h and tk.h headers with it, and which
embeds fake stub startup in such a way that it works with any Tcl setup
(8.3 or later, I think) without needing headers or libs to produce the
shared extension. See http://www.equi4.com/critlib/.

If you want to see what the future holds, there is an even easier way to
add your own C code to your Tcl projects - packaged as scripted document
and based on very recent work by Steve Landers. I'm saying things which
perhaps I should not yet be mentioning, because it is still work in
progress, but the point is that you can create a single tcl file, grab
two files off the net, and assuming you have gcc, it will require one
command to then compile and wrap the whole thing up into a 100% standard
Tcl package (TEA2 compliant, I think, is one of Steve's aims).

The files to grab are:
- two examples, inside http://mini.net/sdarchive/critex.tar.gz
- critcl, the tool, i.e. http://mini.net/sdarchive/critcl.bin
- tclkit for your platform, see http://www.equi4.com/tclkit/
With a bit of footwork, the commands:
cd ex2
critcl -pkg blowfish
Will create a lib/blowfish-0.10/ directory which is ready for use, i.e.
it has the pkgIndex.tcl and all other files and shared libs inside it.

Stay tooned...

</plug>

-jcw

Matthew Swift

unread,
May 9, 2002, 4:34:21 PM5/9/02
to Jean-Claude Wippler
Jean-Claude Wippler wrote:
>
> I'm not sure I understand the issues Matt is raising. But let me try to
> explain why stubs are worthwhile, and also simpler than they look <wink>.
> My apologies if I'm stating the obvious...
>


Thanks for the comprehensive explanation! :-)

The issue I'm trying to raise is this: I've written an extension that
needs its own stub library (much like Incr Tcl). So, on UNIX, I have two
libraries:

1) lib<pkg>1.0.so - the shared library containing its stub vector
2) lib<pkg>1.0.a - the stub library containing the definition of
<pkg>_InitStubs and <pkg>StubsPtr.

The implementation of the <pkg>_InitStubs function in the extension's
stub library is exactly equivalent to that of Itcl_InitStubs in Incr
Tcl: it loads the extension and gets hold of its stub vector using a
call to Tcl_PkgRequireEx.

The problem is the call to Tcl_PkgRequireEx(). The stub library's built
using USE_TCL_STUBS and so this call is actually an indirection through
tclStubsPtr. This means that the caller of <pkg>_InitStubs MUST define
tclStubsPtr.

So does this mean that Tcl applications (i.e. not extensions but
programs based on tclsh) have to be linked against the stub library in
order to get a tclStubsPtr? At first I didn't think so. Firstly because
I assumed that applications shouldn't link against both libtcl8.x.so and
libtclstub8.x.a, and secondly because on UNIX libtcl8.x.so is linked
against tclStubLib.c and therefore defines this symbol. However, on
Windows the tcl8x.dll doesn't define tclStubsPtr.

So I guess it all boils down to a simple yes/no question:

Should Tcl applications (not extensions) link against libtclstub8.x.a /
tclstub8x.lib?

I suppose a seconday question might be: should the Tcl application be
built using USE_TCL_STUBS, even though its linked against libtcl8.x.so?

I think from what you and David are saying the answer is yes. Sorry if
this is all blindingly obvious - I've just always thought of the Tcl
stub library as being intended for extensions only.

Thanks for you help (and patience :-) )

Matt

Matthew Swift

unread,
May 9, 2002, 4:41:06 PM5/9/02
to
David & Jean, thanks for the comprehensive explanations! :-)

I'm being a bit slow though and I'm still not sure I quite understand.
Let me explain the problem a little more clearly this time:

The issue I'm trying to raise is this: I've written an extension that
needs its own stub library (much like Incr Tcl). So, on UNIX, I have
two libraries:

1) lib<pkg>1.0.so - the shared library containing its stub vector
2) lib<pkg>1.0.a - the stub library containing the definition of
<pkg>_InitStubs and <pkg>StubsPtr.

The implementation of the <pkg>_InitStubs function in the extension's

David Gravereaux

unread,
May 10, 2002, 12:04:03 AM5/10/02
to
matthe...@messagingdirect.com (Matthew Swift) wrote:

>David & Jean, thanks for the comprehensive explanations! :-)
>
>I'm being a bit slow though and I'm still not sure I quite understand.
>Let me explain the problem a little more clearly this time:
>
>The issue I'm trying to raise is this: I've written an extension that
>needs its own stub library (much like Incr Tcl). So, on UNIX, I have
>two libraries:
>
>1) lib<pkg>1.0.so - the shared library containing its stub vector
>2) lib<pkg>1.0.a - the stub library containing the definition of
><pkg>_InitStubs and <pkg>StubsPtr.
>
>The implementation of the <pkg>_InitStubs function in the extension's
>stub library is exactly equivalent to that of Itcl_InitStubs in Incr
>Tcl: it loads the extension and gets hold of its stub vector using a
>call to Tcl_PkgRequireEx.
>
>The problem is the call to Tcl_PkgRequireEx(). The stub library's
>built using USE_TCL_STUBS and so this call is actually an indirection
>through tclStubsPtr. This means that the caller of <pkg>_InitStubs
>MUST define tclStubsPtr.

Or, at least, static somewhere at link for the symbol definition. Remember that
tclStubsPtr is in your side, not the core side when using Stubs. When your not
using Stubs, as in the case of a fully static shell, there's no reason to use
the Stubs vector table, but then again, there's no technical limitation
restricting you from it, either.

The added complication of understanding which way is up can be a bit much :-)

"Umm.. so from Tcl's tclStubsPtr which we grab from a Tcl_InitStubs prior, set
our own by the same name and give Tcl our new table. Then this allows
Tcl_PkgRequireEx() in our Stubs library that a third extension is using to grab
our MDXMLA API... pheew!"

EXTERN int
Mdxmla_Init (Tcl_Interp *interp)
{
extern MdXmlaStubs *mdXmlaStubsPtr;
#ifdef USE_TCL_STUBS
if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
return TCL_ERROR;
}
#endif
...
Tcl_PkgProvideEx(interp, "mdXmla", (ClientData) &mdXmlaStubsPtr);
return TCL_OK;
}

>So does this mean that Tcl applications (i.e. not extensions but
>programs based on tclsh) have to be linked against the stub library in
>order to get a tclStubsPtr? At first I didn't think so.

No, you don't need Stubs at this point. But you may. But it's complicated.

I had a BIG issue with Stubs a long time ago after Paul Duffin and Jan Nijtmans
introduced it in 8.1b5 (?). Shells using "load-time" to the core, absolutely
CANNOT be mixed with extensions linked with Stubs. The error happens at the
second level, where, for example, Itk's use of Itcl_InitStubs's call to
Tcl_PkgRequireEx() has no ability to get to the core's tclStubsPtr to resolve
itself. I think this might be what's happening for you. The only solution I
found was to remove the bad apple (the shell's load-time link to Tcl) and use
Stubs and make it all pure. In a sense, what's missing from the Stubs concept,
IMO of course, is a loading mechanism. On windows it's LoadLibrary(), and *nix
some sort of dlload() thing.

Summary: implicit (load-time) linking from a custom shell to the Tcl library
means that ONLY implicit linking can be used for all other extensions used
within that shell (C functions and stuff). They CANNOT be mixed due to the
second level issue regarding Stubs libraries and the confusion around
Tcl_PkgRequireEx() in the provider's Stubs library. Assuming the use of
USE_TCL_STUBS in that library is correct! tclStubsPtr is not available to the
custom shell due to the implicit linkage of Tcl itself. If the shell had used
Stubs to link with Tcl, the now missing loading mechanism needs to be invented.
And would look something like this:


int
KickStartTcl (void)
{
typedef Tcl_Interp *(*LPFN_createInterpProc) ();
LPFN_createInterpProc createInterpProc;
Tcl_Interp *interp;
HMODULE hTclMod;
char appname[MAX_PATH+1];
char *library;

try {

// assume findTcl() knows how to get the right path.
library = findTcl(_tclVer, _exact,
#ifdef _DEBUG
1);
#else
0);
#endif
// load it.
hTclMod = LoadLibrary(library);

if (hTclMod == 0L)
{
std::string err(library);
err.append(" failed to load.");
throw err;
}

// LoadLibrary() loaded the module correctly.
// get the location of Tcl_CreateInterp
createInterpProc =
(LPFN_createInterpProc) GetProcAddress(hTclMod,
"Tcl_CreateInterp");

// What?? no Tcl_CreateInterp export.. ditch out-a-here!
if (createInterpProc == 0L)
{
std::string
err("The Tcl_CreateInterp export was not found in ");
err.append(library);
err.append(".");
throw err;
}

interp = createInterpProc();

// This is why this function exists, to do this! This call engages
// the center of the universe. This is the sun by which our planets
// (extensions) orbit.
if (Tcl_InitStubs(interp, _tclVer, _exact) == 0L)
{
throw std::string(Tcl_GetStringResult(interp));
}
}
catch (std::string &err)
{
MessageBeep(MB_ICONSTOP);
MessageBoxA(NULL, err.c_str(), "Couldn't load Tcl",
MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
return TCL_ERROR;
}

// Discover the calling application.
if (_app == 0L) {
GetModuleFileNameA(0L, appname, sizeof(appname));
_app = appname;
}

_ASSERTE(_app != 0L || *_app != '\0');
Tcl_FindExecutable(_app);

// we're done initializing the core, and now don't need this interp
// anymore.
Tcl_DeleteInterp(interp);
return TCL_OK;
}

> Firstly
>because I assumed that applications shouldn't link against both
>libtcl8.x.so and libtclstub8.x.a, and secondly because on UNIX
>libtcl8.x.so is linked against tclStubLib.c and therefore defines this
>symbol. However, on Windows the tcl8x.dll doesn't define tclStubsPtr.
>
>So I guess it all boils down to a simple yes/no question:
>
>Should Tcl applications (not extensions) link against libtclstub8.x.a
>/ tclstub8x.lib?

Sure. You'll need to invent the loading mechanism.

>I suppose a seconday question might be: should the Tcl application be
>built using USE_TCL_STUBS, even though its linked against
>libtcl8.x.so?

Please, no :) Remove the bad apple, instead, and go Stubs pure.

>I think from what you and David are saying the answer is yes. Sorry if
>this is all blindingly obvious - I've just always thought of the Tcl
>stub library as being intended for extensions only.

Don't put yourself down. This Stubs stuff is far from obvious when it starts
layering. You should have heard Brent Welch, myself, and Scott Redman going
over this stuff when we where working on TclPro for the 1.4 release a couple
Octobers ago. Pheew!

>Thanks for you help (and patience :-) )
>
>Matt

--

Bruce Stephens

unread,
May 13, 2002, 3:35:42 PM5/13/02
to
David Gravereaux <davy...@pobox.com> writes:

> matthe...@messagingdirect.com (Matthew Swift) wrote:

[...]

>>So does this mean that Tcl applications (i.e. not extensions but
>>programs based on tclsh) have to be linked against the stub library in
>>order to get a tclStubsPtr? At first I didn't think so.
>
> No, you don't need Stubs at this point. But you may. But it's
> complicated.

Why is this complicated? What we (I'm a colleague of Matt) have here
is about the simplest case possible: we've got one Tcl extension
(mdXmla) and a Tcl application whose scripts are likely to want to
load it (which is called cgen, but that's of no importance).

This is *exactly* what the stubs system was supposed to handle: we
need to link the application against some specific version of Tcl, but
we'd rather link the extension against the stub library, so that the
extension could be loaded into (say) a test version of tclsh8.4, even
though our application is linked against 8.3.

So it's clear what ought to happen: we compile the extension using
-DUSE_TCL_STUBS, and link the shared library statically against the
stubs library; we compile the application just as we would any Tcl
application, directly against the Tcl shared library (or the static
library, for that matter, provided we didn't disable dynamic loading
or anything).

But we shouldn't link the application against the stubs library,
because, well, that's just not how it's supposed to work---the
application shouldn't need to know that it might be going to load a
stubs-enabled extension. (It's no big deal if we *do* need to do
that, but it's not our understanding of how it ought to work.)

And that all seems to work on GNU/Linux, but not on Windows. On
Windows, there seems to be a problem with tclStubsPtr. So what's
going on?

[...]

>>So I guess it all boils down to a simple yes/no question:
>>
>>Should Tcl applications (not extensions) link against libtclstub8.x.a
>>/ tclstub8x.lib?
>
> Sure. You'll need to invent the loading mechanism.

Huh? I don't understand: if we have to invent something in this
simple case, then surely something's badly wrong. The application is
linked against the Tcl library, and the mdXmla shared library is
trying to get hold of a compatible version of Tcl, so everything
should just work, surely?

[...]

David Gravereaux

unread,
May 13, 2002, 4:09:42 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

>So what's
>going on?

easy. The Stubs library you made for mdXmla was compiled with -DUSE_TCL_STUBS,
but you are linking implicitly with the import library rather than using Stubs.
If you truly do want to use Stubs in a custom shell, you need build it *ALL* for
Stubs and manually call LoadLibrary() to bring in tcl8?.dll

>The application is
>linked against the Tcl library, and the mdXmla shared library is
>trying to get hold of a compatible version of Tcl, so everything
>should just work, surely?

If you used a simple vanilla shell, and just did a `package require mdXmla` from
script, it would work fine. implicit linking and Stubs don't mix. Either build
all of your custom shell for Stubs or don't. Just pick one.

Bruce Stephens

unread,
May 13, 2002, 4:21:23 PM5/13/02
to
David Gravereaux <davy...@pobox.com> writes:

> Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:
>
>>So what's
>>going on?
>
> easy. The Stubs library you made for mdXmla was compiled with
> -DUSE_TCL_STUBS, but you are linking implicitly with the import
> library rather than using Stubs. If you truly do want to use Stubs
> in a custom shell, you need build it *ALL* for Stubs and manually
> call LoadLibrary() to bring in tcl8?.dll
>
>>The application is
>>linked against the Tcl library, and the mdXmla shared library is
>>trying to get hold of a compatible version of Tcl, so everything
>>should just work, surely?
>
> If you used a simple vanilla shell, and just did a `package require
> mdXmla` from script, it would work fine. implicit linking and Stubs
> don't mix. Either build all of your custom shell for Stubs or
> don't. Just pick one.

How is a vanilla tclsh different than an application which links with
Tcl and calls all the same sorts of functions that tclsh does? Is
that, in fact, the problem: are we somehow missing some function that
tclsh calls?

David Gravereaux

unread,
May 13, 2002, 4:41:58 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

>But we shouldn't link the application against the stubs library,
>because, well, that's just not how it's supposed to work

or is it? I do it. It works great on windows and I don't need c:\progra~1\tcl
in my path.

Itcl no longer makes a custom itclsh32.exe. Why? Because the shell is stuck to
a single version of the core and to itself. That's not useful. Trying to make
an itclsh.exe and have version independence to itself, but stuck in one core
version is a new concept to me. I tried to do that like 3 years ago and ran
into the same problem you're having.

If you want to use Stubs, do it all Stubs or don't use Stubs. I've never been
able to mix them. But I can suggest trying this:

/* globals */
struct TclStubs *tclStubsPtr;

int
Tcl_AppInit(Tcl_Interp *interp)
{
tclStubsPtr = ((Interp *)interp)->stubTable;
if (mdXmla_InitStubs(interp, MDXMLA_VERSION, 0) == NULL) {
return TCL_ERROR;
}
...

That might work as a hack assuming you don't try it in 8.0 or less.

David Gravereaux

unread,
May 13, 2002, 5:03:18 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

No, it's your linking. Either implicit through the import library or Stubs and
manual loading of tcl8?.dll. See my last post for a hack idea for mixing.

Bruce Stephens

unread,
May 13, 2002, 5:04:48 PM5/13/02
to
David Gravereaux <davy...@pobox.com> writes:

> Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

[...]

> Trying to make an itclsh.exe and have version independence to
> itself, but stuck in one core version is a new concept to me. I
> tried to do that like 3 years ago and ran into the same problem
> you're having.

That's not what's happening: our application is linked against one
version of Tcl (like tclsh), and we want to have the stubs-aware
extension (mdXmla) use that version too (just as it would if it were
loaded into a tclsh).

This really is a simple situation---we aren't trying to do anything
tricky (although they're interesting problems too), which is why we're
surprised we're getting problems.

> If you want to use Stubs, do it all Stubs or don't use Stubs. I've
> never been able to mix them. But I can suggest trying this:
>
> /* globals */
> struct TclStubs *tclStubsPtr;
>
> int
> Tcl_AppInit(Tcl_Interp *interp)
> {
> tclStubsPtr = ((Interp *)interp)->stubTable;
> if (mdXmla_InitStubs(interp, MDXMLA_VERSION, 0) == NULL) {
> return TCL_ERROR;
> }
> ...
>
> That might work as a hack assuming you don't try it in 8.0 or less.

Yeah, I was wondering about something like that: if it's just
tclStubsPtr, why not hack it as you suggest. But we shouldn't need
to---we're doing something wrong (we've built something wrong or
something).

David Gravereaux

unread,
May 13, 2002, 5:12:42 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

>But we shouldn't need
>to---we're doing something wrong (we've built something wrong or
>something).

No, you're not doing anything wrong, just out-of-the-ordinary. You must be
getting creative or something :)

Bruce Stephens

unread,
May 13, 2002, 5:26:36 PM5/13/02
to
David Gravereaux <davy...@pobox.com> writes:

> Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:
>
>>But we shouldn't need
>>to---we're doing something wrong (we've built something wrong or
>>something).
>
> No, you're not doing anything wrong, just out-of-the-ordinary. You
> must be getting creative or something :)

It can't possibly be *that* out of the ordinary.

We're trying to build a stubs-aware extension. But lots of people do
that. Then we're trying to build a Tcl application, and load the
extension into that---that's less common, but it can't be that hard,
since all we want to do are things that tclsh already does.

In fact, that's probably the way to go: we should look *really*
closely at what tclsh does on Windows, and see what we're doing
differently.

David Gravereaux

unread,
May 13, 2002, 6:03:46 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

>In fact, that's probably the way to go: we should look *really*
>closely at what tclsh does on Windows, and see what we're doing
>differently.

You're probably calling mdXmla functions by way of a Stubs table. Vanilla tclsh
doesn't call *any* extension code by way of a Stubs table. Even when packages
are added to a custom shell, they're static.

Bruce Stephens

unread,
May 13, 2002, 6:15:00 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> writes:

[...]

> This really is a simple situation---we aren't trying to do anything
> tricky (although they're interesting problems too), which is why we're
> surprised we're getting problems.

I guess we *are* doing something slightly more complex than the
simplest case: we're building our own stubs library, and possibly we
don't need to do that. Hmm.

[...]

David Gravereaux

unread,
May 13, 2002, 7:04:29 PM5/13/02
to
David Gravereaux <davy...@pobox.com> wrote:

>Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:
>
>>In fact, that's probably the way to go: we should look *really*
>>closely at what tclsh does on Windows, and see what we're doing
>>differently.
>
>You're probably calling mdXmla functions by way of a Stubs table. Vanilla tclsh
>doesn't call *any* extension code by way of a Stubs table. Even when packages
>are added to a custom shell, they're static.

Umm, most often static.. sorry. Old itclsh31.exe wasn't static -- it was
implicit through an import library.

If the tclStubsPtr symbol could be exported when linked into the Tcl library,
then any custom shell could be dual-mode by providing Tcl's Stubs table, too,
along with the usual import library. I guess oil and water can mix.


D:\tcl_workspace\tcl_head\win>dumpbin release\tcl84.dll /exports| find "tclStubs
"
862 35D 00083684 tclStubsPtr

D:\tcl_workspace\tcl_head\win>


Index: makefile.vc
===================================================================
RCS file: /cvsroot/tcl/tcl/win/makefile.vc,v
retrieving revision 1.90
diff -c -r1.90 makefile.vc
*** makefile.vc 8 May 2002 04:25:35 -0000 1.90
--- makefile.vc 13 May 2002 22:59:08 -0000
***************
*** 437,443 ****
<<
!else
$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcl -out:$@ \
! $(baselibs) @<<
$**
<<
-@del $*.exp
--- 437,443 ----
<<
!else
$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcl -out:$@ \
! $(baselibs) -export:tclStubsPtr @<<
$**
<<
-@del $*.exp

David Gravereaux

unread,
May 13, 2002, 9:10:34 PM5/13/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:

Stubs is for ease in sharing an API so one can cross-mix and use the existing
Tcl_Pkg* stuff for not only loading but now linking, too. And to provide an
abstraction layer for version independence. Like the way Itk needs C APIs from
Itcl. Not like one would use Itk 3.1 with Itcl 3.2, but the possibility to do
such a thing is there without having to rebuild it. I bet it would work, though
after some source code edits.

Stubs are good -- keep it.

It would be nice to have a tclsh.exe where you can specify the version you want
to run by having it linked to Stubs and loading the core manually. IMHO, I feel
that all custom applications that use Tcl, should do the same. They sure would
be easy to upgrade when 8.5 or even 9.0 (assuming a logical compatibility layer)
comes around.

0 new messages