
global variable in shared library?
Wong Ka Chun <95e...@alumni.ee.ust.hk> writes:
(Actually, visibility to the application has nothing to do with shared
memory; this is just a matter of whether the symbol is exported using
a .DEF file or a declspec(dllexport) statement ...)
The whole concept of shared libraries on Linux (and other Unixes) is that
a shared library behaves exactly the same as a statically linked library,
only with different performance characteristics (i.e. it's somewhat slower
when used only once, but saves a lot of memory when lots of applications
use the library at the same time).
The toolchain actually goes through a number of contortions to implement
this behaviour; it's really not trivial (e.g. the initial values of
variables defined in the library but used in the application are copied
to the .dynbss slots; for function pointer comparisons everybody uses
the address of the PLT slot for the function in the main application,
not the address of the function itself; etc.). But while the internals
are complex, the user-visible behaviour is easy to describe: just the
same as statically linking.
In Windows, on the other hand, DLLs have a quite different user-visible
behaviour that statically linked libraries. This makes them easier to
implement, however the user has to be aware of the fact that it's not
a static library (i.e. writing .DEF files and/or using dllexport/
dllimport, possibly fiddling around with ordinals, etc.).
On the one hand, this behaviour has disadvantages compared to the Unix
model: you have two quite different user-visible models of linking to
consider. On the other hand, this makes it possible to use DLLs for a
second purpose at the same time: not just to solve performance problems
by avoiding multiple copies of the same library loaded into memory, but
also to provide for name space encapsulation.
If you want to do this sort of name space encapsulation on Unix, you have
to use some other mechanism -- shared libraries won't do it for you.
However, if you use something else, that will work also when when you
are statically linking ... As the C language doesn't provide for name
spaces, the traditional method has always been to just use a common name
prefix for every module: if you are implementing the 'foo' module,
every global variable or function should have a name that starts with
foo_. If you choose 'foo' distinctive enough, that will work for all
practical purposes ...
B.t.w. nowadays Unix toolchains (including the GNU toolchain used on Linux)
have introduced various additions to the simple model described above.
With the GNU linker, it is in fact now possible to decide on a symbol-
by-symbol basis which global symbols should be visible outside a shared
library and which ones not.
To do so, you'll need to create a 'version script' which looks like:
VERSION_TAG {
global:
foo;
local:
bar;
where you list under 'global' those names that should be visible outside
and under 'local' those that shouldn't; you can use wildcards. You then
specify the version script as argument to the link process. Check out the
ld info pages ('VERSION command') for more details.
Note that this is not portable; other linkers on other Unix platforms
may offer similar features, but the syntax will be completely different ...
--
Dr. Ulrich Weigand
weig...@informatik.uni-erlangen.de