I don't want to rain on anybody's parade, but if C++ classes are being exposed via AmigaOS shared libraries then I fully expect it to work for trivial concrete classes only. Either that, or you write your library functions based on some C structure that then becomes embedded as a delagate within a C++ class wrapper in which a bunch of inline method calls trampoline into your LVO.
I really can't see proper C++ shared code working that way. Not when you factor in things like inheritence, polymorphism and templating. Especially templating...
Templating is one of the lesser evils since it's compile time, and in headers, and so wouldn't be in the compiled library other than to the extent the library uses them itself.
There's two ways of looking at this, the way I see it:
1. He wants to export a C++ API, so that C++ programmers can link with the Amiga resident library and use it via C++. This can either be trivial, or about as hairy as you describe. It is trivial if you make very specific and obnoxious restrictions of people, namely that they use the same C++ compiler or ones that are known to have the exact same object layout. For simple concrete classes with *no* virtual member function you might get away with less, but the moment a single virtual is involved, vtables are involved, and compatibility between C++ classes compiled with different compilers is no longer guaranteed.
Incredibly hairy if he wants it to be generic, in which case the simplest way is to do approach #2 below + re-wrapping the whole thing in a parallel version of the C++ API like you describe.
2. He wants to export a C++ API as Amiga style library functions and is ok with the resulting API being C-style. In that case it's not that bad, since C++ explicitly define what can be exported via C linkage. He'd need to ensure all exceptions get caught in the library and bubbled up as error codes.
He'd also need to wrap all the C++ code in simple functions with valid C signatures that can be exported. Something like this:
void * myclass_new(...) {
return new MyClass(...);
}
sometype myclass_somemember(void * classptr,...) {
return (static_cast
(classptr))->somemember(...);
}
repeat ad nauseam. Easy but tedious.
The gotcha's in general is generally exceptions, multiple inheritance, and assuming too much about memory (if MyClass has a virtual member function anywhere in its ancestry, it is likely to have a vtable pointer at a negative offset from the address you actually get returned from new, but if I remember correctly the exact layout is compiler dependent, so it's necessary to arrange for the user to free the memory with "delete" via a wrapper rather than try to free the memory themselves).
The wrappers must be declared within 'extern "C" { ... }' blocks as well to ensure C linkage.
If you want to get "cute", you can figure out your C++ compilers calling conventions and try to make use of the addresses to the members functions of a class directly to optimize things and do all kinds of nasty stuff, but that's just begging for trouble.