Re: Need to create a C lib - using C++ classes - is it possible
On May 27, 8:31 am, Paavo Helde <nob...@ebi.ee> wrote:
James Kanze <james.ka...@gmail.com> kirjutas:
On May 25, 7:51 pm, "Alf P. Steinbach" <al...@start.no> wrote:
* James Kanze:
[...]
Whether the global symbols in the object are available when
loading other dynamic objects or not. (Specific implementations
of dlopen may have other options, but this basic choice is
specified by Posix.)
and 2) symbols in the root are not available to
dynamically loaded objects under Windows, and are always
available to dynamically loaded objects under Unix.
I'm not sure what you mean here.
I'm not that sure of the terminology myself; by "root", I mean
the code loaded as the initial binary image, before any dynamic
objects have been loaded. When you load a dynamic object under
Unix (using dlopen), you must specify either RTLD_GLOBAL or
RTLD_LOCAL: in the first case, all of the globals in the dynamic
object become accessible to other dynamic objects, in the
second, no. But since it's the operating system which loads the
root, you can't specify anything there. Under Unix, the global
symbols in the root are available to all other dynamic objects,
as if it had been loaded specifying RTLD_GLOBAL. Under Windows,
if I understand correctly, the root is always loaded as if
RTLD_LOCAL had been specified (and the choice for other
dynamic objects is made when they are build, rather than when
they are loaded---but I'm not really that certain about anything
in the Windows world).
In Windows, as you say, one decides separately for each
function or class if it is visible to other modules
("exported") or not. Other modules can only be linked against
exported symbols. In regard of dynamic linking, there is
really no significant difference between "root" .EXE and other
modules. The difference is more related to the typical way how
one builds the whole program (final .EXE depending on a number
of service DLL-s).
That's an interesting requirement. Who invokes this dynamic
linking, then, if not the executable?
In Windows, the dynamic dependencies are resolved and checked by the
static linker. The linker checks that all symbols are actually
resolvable, and encodes the appropriate filename into the linked module.
This pretty much means that the dependency graph of loadable modules is a
directed one, without any cycles. For implicit loading of the whole
program into memory the root module (final .EXE) has to be linked last,
thus no implicitly loaded DLL can have symbols resolved by the .EXE
module (modulo some file renaming trickery or out-of-date file versions,
of course).
However, this is different for plugin-style DLL-s, which are
loaded explicitly during the run by the program itself. These
DLL-s can easily make use of symbols defined by the .EXE
module. In some cases I have seen the .EXE itself is only a
thin envelope application providing the main GUI window frame,
and 99% of the application functionality is provided by
dynamically loaded plugins, incidentally linked against to the
.EXE module for using some shared service functions.
In other words, the only constraints are those due to order of
loading.
To get this a bit more on-topic, I compare the Windows model
with Linux dynamic loader. There are both pros and cons:
Pros:
In a Windows build, if a module has been built successfully one
knows that all its dependencies have been resolved. In Linux one can
easily have a .so file with unresolved dependencies. This can be checked
and avoided of course, with a little extra work in Makefiles.
A dynamic symbol cannot be accidentally reseated into another
module, which happens to export the same symbol.
That's true under Unix as well, IF the symbol in question is in
a module loaded with RTLD_LOCAL (or if the user takes other,
more specific, but platform dependent steps).
Cons:
One cannot have dependency cycles among dynamically loaded modules=
..
Actually I think this is rather a "pro".
Yes and no. But if I understand your explination correctly, you
can in fact have cycles under Windows as well, if the modules
are explicitly loaded (e.g. as plugins), and that's probably the
only time you'd want them. (The root used, and thus depends on,
various plugins, and the plugins use common functionality in the
root.)
A dynamic symbol cannot be willingly reseated into another module,=
making things like Electric Fence cumbersome to implement, and causing
Microsoft to invent layers and layers of debugging interfaces and
subsystems.
Rather a special case.
If the modules are linked against different versions of C or C++
runtime libraries, it becomes difficult to exchange objects using
resources provided by these libraries (FILE*, malloc(), std::vector,
etc.).
Any dynamic linking introduces any number of additional problems
with regards to version management, binary compatibility, etc.,
and it's better to avoid it except where the advantages outweigh
these costs. Basically, about the only implicit dynamic linking
which I'd use is that of the system ABI (to ensure portability
to different versions of the system) and low level libraries
which can be more or less assimilated to the system (data base
interface, etc.). Under Unix (my usual platform), I don't think
I've ever invoked dlopen except with RTLD_LOCAL, and except for
the bundled system libraries and Sybase, I don't use any
implicit dynamic linking. Under Windows, I rather suspect that
I'd do likewise---including dynamic linking for the system API
and low level functions like malloc. (But I'm not sure: it
partially depends on what is bundled with the OS, since you
don't want to have to deliver additional system level DLL's with
your application.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34