Amiga.org

Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: andst on December 05, 2012, 05:22:44 PM

Title: C++ shared libs?
Post by: andst on December 05, 2012, 05:22:44 PM
Hey,

As you may know I'm working on wxWidgets for Amiga (http://portingwx.blogspot.com/).  It's a C++ lib and can get pretty big, so making it shared is clearly desirable.  OS 4 shared objects should be straightforward enough, but I'm wondering about normal resident libraries:

Has anyone done a resident C++ library before?

I'd be interested in experiences and sample code if possible.  Both for ppc and m68k.

Are people using C++ on Amiga to any extent btw?  Or is it still mainly C and other languages?

//A.
Title: Re: C++ shared libs?
Post by: SamuraiCrow on December 05, 2012, 06:44:32 PM
Quote from: andst;717624

Has anyone done a resident C++ library before?


Nope.  You'd be the first.

Keep in mind that the interface "feature" of OS 4 is not available on OS 3 so you wouldn't be able to use any object-oriented features within the library code.

Quote
I'd be interested in experiences and sample code if possible.  Both for ppc and m68k.

Are people using C++ on Amiga to any extent btw?  Or is it still mainly C and other languages?


Not really.  It's mainly C and other languages.  I rather like AmigaE but the library mode is severely broken on it.
Title: Re: C++ shared libs?
Post by: billt on December 05, 2012, 06:51:23 PM
I'd also ask on os4coding.net as that is more oriented for programming, though it is specific to OS4 but should get you some answers that may be relevant to OS3.x as well.
Title: Re: C++ shared libs?
Post by: andst on December 05, 2012, 07:39:57 PM
@billt

Ok Bill, that's a good suggestion.  Will do.

@SamuraiCrow

Ok thx, in theory I'm thinking it *should* work, but I'll allocate some thinking time to figure it out.
Title: Re: C++ shared libs?
Post by: psxphill on December 05, 2012, 08:20:35 PM
Quote from: SamuraiCrow;717627
Nope. You'd be the first.

According to this:
 
http://www.amigareport.com/ar131/p1-7.html
 
It's possible with SAS/C 6.5
 
"Better Support for Shared Libraries and Devices

You can build your shared libraries in C++!  You can use C++ member functions
as library entry points, including constructor and destructor functions.
Encapsulate your entire C++ class as an AmigaDOS shared library."
Title: Re: C++ shared libs?
Post by: bloodline on December 05, 2012, 09:31:22 PM
Quote from: psxphill;717649
According to this:
 
http://www.amigareport.com/ar131/p1-7.html
 
It's possible with SAS/C 6.5
 
"Better Support for Shared Libraries and Devices

You can build your shared libraries in C++!  You can use C++ member functions
as library entry points, including constructor and destructor functions.
Encapsulate your entire C++ class as an AmigaDOS shared library."
That sounds cool!!! :)
Title: Re: C++ shared libs?
Post by: Karlos on December 05, 2012, 11:23:30 PM
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...
Title: Re: C++ shared libs?
Post by: vidarh on December 06, 2012, 12:33:55 AM
Quote from: Karlos;717689
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.
Title: Re: C++ shared libs?
Post by: vidarh on December 06, 2012, 12:36:51 AM
Quote from: andst;717624
Hey,

As you may know I'm working on wxWidgets for Amiga (http://portingwx.blogspot.com/).  It's a C++ lib and can get pretty big, so making it shared is clearly desirable.  OS 4 shared objects should be straightforward enough, but I'm wondering about normal resident libraries:


See my longer reply to Karlos re: the issues with making it a normal resident lib.

Re: shared objects: Be aware that C++ shared objects are *not* trivial. The name mangling is compiler specific, and other features also have lots of implementation dependency issues. You can avoid most of the problems if you can mandate a specific compiler, but C++ is really not well suited for this.

This may or may not be a big deal to you, but figured I'd make sure you're aware.
Title: Re: C++ shared libs?
Post by: Karlos on December 06, 2012, 12:53:56 AM
Quote from: vidarh;717715
Templating is one of the lesser evils since it's compile time, and in headers


Not always. It's pretty common practise to provide template specialisations that are compiled once and used as a common base for multiple types. For example, you create some container type. Every MyContainer implementation can be reduced to a specialisation for void*, in which the remaining template just becomes a type safety wrapper. It's a well recognised strategy to avoid template bloat.
Title: Re: C++ shared libs?
Post by: vidarh on December 06, 2012, 01:33:56 AM
Quote from: Karlos;717720
Not always. It's pretty common practise to provide template specialisations that are compiled once and used as a common base for multiple types. For example, you create some container type. Every MyContainer implementation can be reduced to a specialisation for void*, in which the remaining template just becomes a type safety wrapper. It's a well recognised strategy to avoid template bloat.


True. But in this case MyContainer once the template is instantiated is just another class. It is implemented in terms of a template, but there's nothing special about the instantiation of the template, and the implementation issues if you try to link it with non-C++ code are exactly the same as if you were to manually expand the template and write it out as a "plain" C++ class.
Title: Re: C++ shared libs?
Post by: bloodline on December 06, 2012, 06:50:39 AM
Couldn't Andst use the Amiga's native OOP system, of BOOPSI or is that just too crude for this task... I must confess to not really reading what he is trying to do :)
Title: Re: C++ shared libs?
Post by: andst on December 06, 2012, 01:32:15 PM
Quote from: bloodline;717753
Couldn't Andst use the Amiga's native OOP system, of BOOPSI or is that just too crude for this task... I must confess to not really reading what he is trying to do :)

Hey, a good discussion going on here!  And this is a fair question.

The wxWidgets toolkit can be described as a C++ wrapper for native API's.  So you'd write code using wxWidgets classes, and the resulting program would use Win32 on Windows, GTK on Linux, Cocoa on OSX, and on Amiga it would indeed be BOOPSI/Reaction.

What I've found is that it speeds up GUI generation a lot, and makes multi platform support a no-brainer.  And then use something like DialogBlocks, and it's as quick and powerful as anything out there on any platform.
Title: Re: C++ shared libs?
Post by: andst on December 06, 2012, 01:45:02 PM
Quote from: vidarh;717716
See my longer reply to Karlos re: the issues with making it a normal resident lib.

Re: shared objects: Be aware that C++ shared objects are *not* trivial. The name mangling is compiler specific, and other features also have lots of implementation dependency issues. You can avoid most of the problems if you can mandate a specific compiler, but C++ is really not well suited for this.

This may or may not be a big deal to you, but figured I'd make sure you're aware.


Thanks.  I expect this would be more or less the same as on other platform though (Unix) and not specific to Amiga shared objects.  wxWidgets already builds with shared objects on Linux, so the support is already there.

The libraries do end up being compiler specific on other platforms too though.  This is mostly a generic C++ issue as I understand it, and nothing I'll try to change in this project.  On Amiga it might be less of an issue as I understand G++ would be by far the most widely used C++ compiler atm.

As far as templates, I haven't looked in detail at what symbols g++ exports, but I expect if would be more or less the same as if the class were expanded, just like you describe.
Title: Re: C++ shared libs?
Post by: andst on December 06, 2012, 02:05:29 PM
Quote from: vidarh;717715


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).


Vtables end up as regular symbols as far as I can tell.  Compiler dependent yes, but in theory should be fine.  Not sure if they could be shared between processes, but libs with some separate data per process is fully possible if I remember correctly.  I'm not sure I quite follow you w.r.t memory, do you mean correct C++ code might fail, or that broken user code would fail?

Multiple inheritance and exceptions aren't heavily used in wxWidgets so it might not be a huge issue.  I think exceptions can even be turned off without sacrificing too much functionality, in case they become a major bother.
Title: Re: C++ shared libs?
Post by: andst on December 06, 2012, 02:24:52 PM
Quote from: Karlos;717689
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...


Ok, well it definitely needs to work for abstract classes as well if it's going to work with wxWidgets.  There's not too much multiple inheritance, but plenty of inheritance, polymorphism and templating obviously.  wxWidgets doesn't use all the more recent complex features of C++, but these basic building blocks are used quite frequently.

The SAS/C example is evidence that at least *some* incarnation of a C++ shared library is possible on Amiga.  SAS/C won't be able to compile wxWidgets, but I'm perfectly open to modifying gcc/g++ if needed.  I'm also thinking that C++ shared libraries works with DLL's on Windows.  Without knowing in detail exactly how it's done for DLL's, in my experience regular DLL's have mostly similar functionality to Amiga resident libraries.  Or is there any critical feature of DLL's that is missing from Amiga resident libraries?

Thanks all for responding.  Keep it going!
Title: Re: C++ shared libs?
Post by: psxphill on December 06, 2012, 02:59:20 PM
Quote from: andst;717776
The SAS/C example is evidence that at least *some* incarnation of a C++ shared library is possible on Amiga. SAS/C won't be able to compile wxWidgets, but I'm perfectly open to modifying gcc/g++ if needed. I'm also thinking that C++ shared libraries works with DLL's on Windows. Without knowing in detail exactly how it's done for DLL's, in my experience regular DLL's have mostly similar functionality to Amiga resident libraries. Or is there any critical feature of DLL's that is missing from Amiga resident libraries?

I'm not sure that you can derive from a C++ class in Windows DLL's either, that is what COM is for. COM standardises on what the vtable's look like and how to cast from one object type to another. I would guess that the AOS4 libraries are similar to COM.
 
There is no reason at all why it can't be done on AOS3, but you'll need to add compiler support & then you will be limited to that one compiler (but I guess you have that problem on AOS4 too). I don't know how SAS/C does it and whether it's worth copying their method or not.
Title: Re: C++ shared libs?
Post by: vidarh on December 06, 2012, 04:28:31 PM
Quote from: andst;717775
Vtables end up as regular symbols as far as I can tell.  Compiler dependent yes, but in theory should be fine.  Not sure if they could be shared between processes, but libs with some separate data per process is fully possible if I remember correctly.  I'm not sure I quite follow you w.r.t memory, do you mean correct C++ code might fail, or that broken user code would fail?


Broken user code would fail. The only issue there is that for every function wrapping a "new" operator there needs to be an equivalent one calling "delete" and users of the library needs to know they *must* use those to free the objects rather than, say, calling FreeMem().

But this is the same as in any C++. I mentioned it mainly in the context of the possible scenario with wrapping the C++ API in a C layer which could make it less obvious to a user. If you hand a user the actual C++ objects and have them use it from code compiled with the same compiler, then having to call delete presumably wouldn't surprise anyone.
Title: Re: C++ shared libs?
Post by: andst on December 06, 2012, 07:12:49 PM
Quote from: psxphill;717783
I'm not sure that you can derive from a C++ class in Windows DLL's either, that is what COM is for. COM standardises on what the vtable's look like and how to cast from one object type to another. I would guess that the AOS4 libraries are similar to COM.
 
There is no reason at all why it can't be done on AOS3, but you'll need to add compiler support & then you will be limited to that one compiler (but I guess you have that problem on AOS4 too). I don't know how SAS/C does it and whether it's worth copying their method or not.


Ok, well perhaps better to be limited to one compiler than no compiler at all.  But I guess it's also becoming clear to me that there is limited previous work in the area.  At least now I know a bit more about which areas need some thinking.
Title: Re: C++ shared libs?
Post by: andst on December 06, 2012, 07:31:45 PM
Quote from: vidarh;717795
Broken user code would fail. The only issue there is that for every function wrapping a "new" operator there needs to be an equivalent one calling "delete" and users of the library needs to know they *must* use those to free the objects rather than, say, calling FreeMem().

But this is the same as in any C++. I mentioned it mainly in the context of the possible scenario with wrapping the C++ API in a C layer which could make it less obvious to a user. If you hand a user the actual C++ objects and have them use it from code compiled with the same compiler, then having to call delete presumably wouldn't surprise anyone.


Okay.  There probably little need for FreeMem() in any wxWidgets user code, and in my experience it's even unusual to use the delete operator much, as object removal is pretty much always automatic.  It's different for library code obviously, but I guess there it's easier to influence code content  ;-)
Title: Re: C++ shared libs?
Post by: itix on December 06, 2012, 08:39:31 PM
Quote from: andst;717624
Hey,

As you may know I'm working on wxWidgets for Amiga (http://portingwx.blogspot.com/).  It's a C++ lib and can get pretty big, so making it shared is clearly desirable.  OS 4 shared objects should be straightforward enough, but I'm wondering about normal resident libraries:


There are no shared objects in OS4. It is just using dynamic linking. Due to way Amiga operating systems work you cant have shared objects.

Quote
Has anyone done a resident C++ library before?


I have created libraries which are written in C++ but not libraries which expose C++ interface. It simply isnt possible because library system was not designed for that.

Quote
Are people using C++ on Amiga to any extent btw?  Or is it still mainly C and other languages?


It is mainly C and other languages.