Newsgroups: comp.windows.x
Path: utzoo!utgpu!watserv1!watdragon!watsol.waterloo.edu!tbray
From: tbray@watsol.waterloo.edu (Tim Bray)
Subject: Flaw in Xt init sequence (but with simple fix)
Message-ID: <1991Feb28.005057.24723@watdragon.waterloo.edu>
Sender: daemon@watdragon.waterloo.edu (Owner of Many System Processes)
Organization: University of Waterloo
Date: Thu, 28 Feb 1991 00:50:57 GMT
Lines: 84

Suppose I have a widget set called Xn. Suppose I need some general-purpose
initialization done.  This is generally done by having a file called Vendor.c,
and in it declaring a global variable called 

applicationShellWidgetClass

which is a complicated Xt structure containing, among other things, pointers
to several initialization routines.

Then, in XtAppInitialize, the following call gets my Xn code involved in the
initialization logic, and it all works hunky-dory...

    root = XtAppCreateShell(NULL, application_class, 
			    applicationShellWidgetClass,dpy, merged_args, num);

The the programmer builds her application, and eventually something like the
following happens:

cc -o app app.o -lXn -lXt -lX11

But wait!  Suppose the widget set doesn't need any particular initialization,
and hasn't bothered to define the applicationShellWidgetClass global?  No
problem, because libXt has its own Vendor.c, which has its own
applicationShellWidgetClass, which has pointers to some routines that do
something or other, and that'll get linked in if one hasn't already been
provided.

GENERAL CLAIM: this kind of dependence of on the semantics of the unix linker
is unclean, unportable, and downright icky.

SAMPLE PROBLEM: IBM's AIX on the RS/6000 supports shared libraries.  Shared
libraries are a Good Thing; in fact with software as bloated as Xlib, Xt and
Xn, it verges on criminal negligence not to use them if they're there.
However, the shared-lib builder on AIX handily pre-resolves all the unresolved
pointers.  So if you execute the cc command line above, and Xt has been built
shared, the applicationShellWidgetClass is already pointing at the Xt version,
and the first time you try to XtCreate an Xn widget, you go up ingloriously in
smoke.  Am currently looking at various solutions involving different hacks
and kludges.  And in the interim, running N applications that each carries its
own copy of Xt, Xn, and X11 around.

PROPOSED SOLUTION:  We need two new function calls.  Require an entry point in
each widget set with a nice standard name; in this case

void * XnGetApplicationShell();

(void *) because I think those are Xt data structures that application code
doesn't want to know about.  If the widget set doesn't need to initialize, the
entry point just returns NULL.  No args necessary, I think.

Then you have another call, a carbon copy of XtAppInitialize() with 1 more
argument, as follows:

Widget
XtAppInitializeW(app_context_return, application_class, options, num_options,
		 argc_in_out, argv_in_out, fallback_resources, 
		 args_in, num_args_in, application_shell)
XtAppContext * app_context_return;
String application_class;
XrmOptionDescRec *options;
Cardinal num_options, *argc_in_out, num_args_in;
String *argv_in_out, * fallback_resources;     
ArgList args_in;
void *application_shell;

Then, down its guts, it says:

    if (application_shell)
      root = XtAppCreateShell(NULL, application_class, 
	  		      application_shell, dpy, merged_args, num);
    else
      root = XtAppCreateShell(NULL, application_class, 
	  		      applicationShellWidgetClass, dpy, merged_args, 
                              num);

If it isn't obvious, you use the return from XnGetApplicationShell() as the
last argument to XtAppInitializeW().

Of course, you'd want to have an analogous form of XtInitialize() and maybe
some of those other init calls.

Or am I missing some terribly obvious point?

Cheers, Tim Bray, University of Waterloo
