ID Number: Q72651
5.05 5.10 5.11 5.13 | 5.05 5.10 5.11 5.13
MS-DOS | OS/2
Summary:
Weak externals are a special type of extern reference that allow the
linker to use an alternate symbol to fix up an address. Through the
use of a weak external record, a library developer can have an
alternate symbol used if no other references are made to the module
where the primary symbol resides.
The Microsoft Incremental Linker (ILINK) does not provide support for
this type of record and will return the following error message if it
encounters a weak extern record:
fatal error L1246: weak externals not supported
To work around the problem, perform a full link.
More Information:
You can create weak externals with the Microsoft Macro Assembler
(MASM) version 6.0, which will allow you to specify an alternate
symbol when defining an EXTRN. MASM takes this alternate ID and
creates both a standard EXTDEF record for the primary symbol and a
COMENT record with the alternate symbol in the object file.
The COMENT record tells LINK and LIB to treat the alternate symbol as
a "weak" external reference. If there are no other references to the
module in which the standard symbol resides, LINK will use the weak
extern address to fix up the reference.
For example, assume you write some functions in assembler to perform
some housekeeping chores and you put these functions in your library.
In addition, you might write one function that calls these various
housekeeping functions. For example:
EXTRN _InitHeap:near
EXTRN _InitFile:near
EXTRN _InitKbd:near
InitLib PROC NEAR
call _InitHeap
call _InitFile
call _InitKbd
InitLib ENDP
Each of these functions (_InitHeap, _InitFile, and _InitKbd) may
reside in a module that defines the functions and symbols each
subsystem uses. For instance, here is a sample LIB listing showing the
possible contents of the module in which _InitKbd resides:
KbdStuff Offset: 00000010H Code and data size: 915H
_InitKbd _ReadKey _SendKey _KeyBuffer
_FlushKey _ScanCode _CharCode _BiosState
_Int16Handler _CtrlBrkStat _EchoState
Regardless of whether the program uses anything else from the KbdStuff
module, the entire module is linked into the .EXE. If none of the
other modules are required for the program, the _InitKbd function
might not be required either. Thus, using regular EXTRNs, you have
added dead code (that is, the rest of the KbdStuff module) to the
.EXE, and you have also executed code (_InitKbd) that is not necessary.
Now, reconsider this example with the use of weak externals. Just
change the EXTRN statement to specify an alternate symbol. For
instance:
EXTRN _InitKbd(_EmptyInit):near
Here is the _EmptyInit code:
_EmptyInit PROC NEAR
ret
_EmptyInit ENDP
The linker can now use the weak external _EmptyInit to resolve the
reference to _InitKbd if none of the other symbols in the KbdStuff
module are needed. If other symbols in KbdStuff really are referenced,
the original _InitKbd symbol will be used.
The same situation applies to data symbols. For instance, you may want
to set a flag to indicate if a branch in your code should be taken
based on other modules that may be linked in. Once again, you just add
the default and alternate resolution to the EXTRN statement and
assemble the code. The linker will use the one that is needed.
Note: Assume you define the same alternate reference with two
different primary references in two separate modules as follows:
MOD1.ASM
--------
EXTRN Primary1(Alternate):near
MOD2.ASM
--------
EXTRN Primary2(Alternate):near
In this case, LINK will generate the following warning:
warning L4067: changing default resolution for weak external
'symbol' from 'oldresolution' to 'newresolution'
When this happens, LINK uses the default reference from the second
module in both cases (Primary2 in this example).
For more information on the EXTRN directive, the see the online help
and section 8.4.2 of the "Microsoft Macro Assembler Programmer's
Guide" for version 6.0.
For more information on the weak extern (WKEXT) .OBJ record format,
see section 2.11 of the "Microsoft C Developer's Toolkit Reference."