Re: C++ and shared objects
And thus spake James Kanze <james.kanze@gmail.com>
Tue, 9 Feb 2010 13:12:33 -0800 (PST):
The POSIX standard does *not* require it (although as you say,
most Unix compilers do have it). The example in the POSIX
standard doesn't use it; it uses something like:
void (*pf)();
*(void**)(&pf) = dlsym("function");
You mean defining a pointer to the function in question
alongside it and retrieve the address of that pointer rather
than the address of the function itself. Yes, that used to be
the only correct workaround, to my knowledge. However, one small
final nitpick: the current version of the POSIX standard (i.e.,
v7) does actually require the possibility of the conversion:
http://www.opengroup.org/onlinepubs/9699919799/functions/dlsym.html
'The ISO C standard does not require that pointers to functions
can be cast back and forth to pointers to data. However,
POSIX-conforming implementations are required to support this,
as noted in Pointer Types . The result of converting a pointer
to a function into a pointer to another data type (except void
*) is still undefined, however.'
(Note that in C++, since you're passing an unmangled name, you'd
have to write the first statement:
extern "C" {
void (*pf)();
}
In most cases, this is IIRC not even really necessary, since the
calling convention for functions is actually most often
identical (apart from name mangling, which is irrelevant for the
receiving pointer). But you are right, to be on the safe side it
should be declared like that.
Yes. But the same trick as POSIX requires above can be used in
reverse; both function and data pointers do in fact have the
same size and representation under Windows.
As they have on most systems in use today. On Windows, this is
not really a problem, since the manufacturer of both the
operating system and the compiler is one and the same, so there
is not even potential for conflict. The fact that neither C nor
C++ specify that a function pointer and an object pointer have
to have identical size, does not mean that they are not allowed
to (and I do not know an example where they are actually
different).
But the new operator doesn't require an object for a class. But
yes, I think I missed your point. IIUC, what you're saying is
that you can't use dlsym directly to obtain a newed object.
Which is correct: of necessity, it returns the address of
something that has static lifetime (in the sense of the
standard).
What I meant was that this is impossible:
DO_SOMETHING_MAGICAL_WITH_DLSYM("ClassThatWasNotKnownBefore");
KnownBaseClass* = new ClassThatWasNotKnownBefore;
this simply cannot work since C++ (like C) is statically typed.
One cannot 'load' a type, since it is not a first-class entity.
E.g. in Python this is different, due to 'everything is an
object' (even the class itself). I am serious: if this is
possible, please show me how. I'm a curious person. :-)
What is indeed possible is to use a factory and two-phase
construction, and so far that is the only way I know of:
ClassFactory.load_from_file("filename.so", "MyClass");
BaseClass* instance = ClassFactory.instantiate("MyClass");
instance->set_parameters(param_map);
Regards,
Robert