[Openal-devel] Using C++ in ALUT?

Chris Robinson chris.kcat at gmail.com
Mon Jun 2 23:09:14 PDT 2008


Oops. Realized I accidently sent this message to Killian directly yesterday by 
accident. Since it contains info on how it'd work, I think it's relevant to 
resend (sorry Killian)..

On Sunday 01 June 2008 11:23:01 pm you wrote:
> IMO,
> Depends on who "owns" the code .
> But you could wrap it (and don't compile it, but offer it as a header
> (so you don't get overhead)) :
> Ow and we'd need a new standard to allow this (otherwise it will not
> work on all  openal implementations) very important !!!

Thanks for the input. Actually, in my mind it would work something like this..

* alut.h:
#ifdef __cplusplus
extern "C" {
#endif
...
typedef struct alutStream alutStream;
ALUT_API alutStream* ALUT_APIENTRY alutCreateStreamFromFile(const char*);
ALUT_API ALboolean ALUT_APIENTRY alutIsStreamPlaying(alutStream*);
ALUT_API void ALUT_APIENTRY alutDestroyStream(alutStream*);
...
#ifdef __cplusplus
}

// Extra C++ stuff
struct alutStream {
    virtual ALboolean ALUT_APIENTRY IsPlaying() = 0;
    ...
    virtual ~alutStream(){};
};
#endif


* implementation.cpp (in the lib):
#include "AL/alut.h"
struct StreamImpl : public alutStream {
    virtual ALboolean ALUT_APIENTRY IsPlaying()
    {
        return (this->Pos >= this->EndPos);
    }
    ...
    StreamImpl(const char *fname)
    {
        ...create/initialize everything...;
    }
    virtual ~StreamImpl()
    {
        if(SourceID)
            alSourcei(SourceID, AL_BUFFER, 0);
        alDeleteBuffers(BufferCount, Buffers);
    }

private:
    ALuint BufferCount;
    ALuint *Buffers;
    ...
};

extern "C" {

ALUT_API alutStream* ALUT_APIENTRY alutCreateStreamFromFile(const char *fname)
{
    return new StreamImpl(fname);
}

ALUT_API ALboolean ALUT_APIENTRY alutIsStreamPlaying(alutStream *stream)
{
    return stream->IsPlaying();
}

ALUT_API void ALUT_APIENTRY alutDestroyStream(alutStream *stream)
{
    delete stream;
}

...
}

***
All C users would see is an opaque alutStream pointer, and a C++ user would 
see the public interface functions. In both cases, it'll use the fully 
implemented StreamImpl struct/class, but they won't see anything that we 
don't choose to make public.


Additionally, through the magic of inheritance, it'll allow crafty developers 
to override the default implemention, while keeping the API calls exactly the 
same. eg:

usercode.cpp:
struct MyStream : public alutStream {
    virtual ALboolean ALUT_APIENTRY IsPlaying()
    {
        return this->WhenISayItsDone;
    }
    ...
};

alutStream *stream1 = new MyStream;
alutStream *stream2 = alutCreateStreamFromFile("somefile.ogg");

Then both:

if(alutIsStreamPlaying(stream1) &&
   alutIsStreamPlaying(stream2))
and
if(stream1->IsPlaying() && stream2->IsPlaying())

are perfectly valid, with completely expected and standard C++ behavior. This 
could be very useful, for example, if a developer doesn't want to assume the 
user's ALUT can support, say, MP3 for licensing reasons, though the developer 
has it licensed but doesn't want to sacrifice what else the user's ALUT can 
handle (eg. Vorbis, FLAC). They can make their own implementation to deal 
with MP3 and use it as needed, while using alutCreateStreamBlah for 
everything else.


More information about the Openal-devel mailing list