Re: C++ and shared objects
On Feb 8, 6:46 am, Robert Fendt <rob...@fendt.net> wrote:
And thus spake Phoenix87 <phoenix1...@gmail.com>
Sun, 7 Feb 2010 16:14:50 -0800 (PST):
I want to build some shared libraries from C++ code defining
classes because I want to load them dynamically in programs
that need that classes. I've read about dlopen and co.,
which require the implementation of factory procedures in
order to dynamically allocate class instances from the
loaded shared object. Is there an alternative way to
dynamically load classes in C++ programs? I mean something
which allows to instantiate new class instances with new
keyword etc...Basically my question is quite the same thing
as asking how the STL, or the CERN ROOT libraries work.
STL is a template framework. It therefore does not consist of
any runtime libraries apart from the C standard stuff
It depends on what you mean by "STL". Traditionally, it did
refer to a library created by Stepanov, which in fact was almost
exclusively templates. Most people today, however, use the term
STL to refer to the standard library. In which case, it's
provided somehow by your compiler, and you don't really have to
know the details. (And it's not all templates.)
Of course, the real problem is that he doesn't really say what
he's trying to do, so it's difficult to find a solution. In
general, if you're providing a library for other programs,
you'll provide a set of headers, a dynamic object *and* a static
library, since except in exceptional cases, the client will
probably prefer linking statically. (If nothing else, unless
you're freeware, the licensing issues for DLL's will be a
In order for a direct 'new' to work, the class definition has
to be available (header file) as well as the object files
containing all non-inline functions.
And in order for a factory method to work, and external
declaration of the factory method must be present. And to use
whatever the factory method returns, you also need headers which
declare the interface. In the end, it's purely a question of
what and how you want to provide something.
So you just can build a shared library of your stuff and use
it for regular compiling and linking against. In this case,
the system's runtime facilities will do the loading of the
dynamic library for you at program startup.
With some notable exceptions, if that's the case, you should
probably be linking statically.
This is straight-forward, and I do not interpret your question
in that direction. You seem to think about dynamic loading
rather than dynamic linking.
Dynamic loading means that you load something your compiler
did not know about. If you look at the specifications of
dlopen() and such (the Windows equivalents have similar
restrictions), you will find that the framework just allows
for retrieval of unmangled (i.e. plain C) symbols. This works
for constants and for function pointers (although the ability
to retrieve a function pointer directly through dlsym() is
technically a non-standard compiler extension, albeit a
The interface (both under Unix and under Windows) allows for
loading just about anything. (Windows is somewhat more
restrictive here, I think.) All you have to do is give the name
according to the local conventions, which means mangled in the
case of Windows or Unix. On the other hand, you also have the
problem that the function returns a void* (Unix) or a void (*)()
(Windows), which means you'll also need some casting. And no
doubt, headers, to define what you'll be casting to. In
practice, because of the mangling, the easiest solution is to
provide an ``extern "C"'' factory function. (Typically, the
mangling used by C is far simpler than that used by C++.) But
the client code still needs the header files to know the target
type of the cast, and the type actually returned.
Long story short: you really can only get a pointer to a
factory function by using dlsym() (POSIX) or GetProcAddress()
(Windows). There is no way around it, just live with it.
That's false. With both, you can get a pointer to anything.
And if the library contains classes which have been exported
(and under Unix, by default, everything has been exported), you
can new them. But you need a header file with the concrete type
to do so.
Loading C++ classes directly would involve all sorts of pains
and hassles, not to mention a change to the C++
specifications, and since at least POSIX does not deal with
C++ anyway, dlsym() will not be changed in the near future. I
do not know about Microsofts's plans for VC and
GetProcAddress, but I would be surprised.
GetProcAddress is almost exactly like dlsym, except that it
returns the address of a function, rather than the address of
data, But since both Windows and Unix require the two to have
the same representation, all it takes is some very ugly funny
casting to get from one to the other. (As luck would have it,
every time I've used dlsym, I've needed the address of a
function, but the first time I used GetProcAddress, it was to
obtain the address of data.)
In general, I think what you're trying to say is correct, but
the issues are far more complicated than one would guess from