0

I'm having some trouble making a callback wrapper class method that needs to be used by a third party library; the JackAudio library.

I have been able to make a wrapper for a JackAudio callback function that needs two arguments.

I'm just having trouble creating a callback function for a particular function that needs a const char * as an argument.

So far I have been able to make the JackAudio library jack_set_sample_rate_callback function use a custom class and can be executed like so:

SoundClass Sound;

SoundClass * SoundPointer = &Sound;

jack_set_sample_rate_callback( 
                              client, 
                              SoundClass::SampleRateCallbackWrapper, 
                              SoundPointer 
                             );

And the class looks something like this:

SoundClass
{

int SampleRateCallback( jack_nframes_t nframes )

    {
        //executes some code when called.
    }

 static int SampleRateCallbackWrapper( jack_nframes_t nframes, void * arg )
    {
        return static_cast < SoundClass* > ( arg )->SampleRateCallback( nframes );
    }
};

All of the above works well, with no issues.

The problem I'm having now is with the JackAudio callback function jack_set_error_function

This is what I tried:

static void  ErrorCallbackWrapper( const char * arg  )
{
    return static_cast < SoundClass*>( arg )->SomeErrorFunction();
}

But I get error: invalid static_cast from type ‘const char*’ to type ‘SoundClass*’

I get the gist why this is happening, I just have no idea what to do for a solution.

Thanks in advance for any help guys.

Tek
  • 2,888
  • 5
  • 45
  • 73
  • I want to use a class function in the callback argument of the function `jack_set_error_function`. I thought that was clear. – Tek Dec 24 '12 at 03:08

1 Answers1

2

Assuming the Jack API is written for the C language, there is a formal problem already with the working callback that you have. Namely that it then needs to be extern "C", and that as a static member function it cannot be. So formally it needs to be a free-standing function.

The documentation that you link to for the jack_set_error_function gives this signature, presumably expressed in C:

void jack_set_error_function( void(*)(const char *) func);

For C++ the callback must be assumed to be extern "C", so,

extern "C" void MyErrorFunction( char const* errorMessage )
{
    // Whatever, e.g. post a message to the GUI event queue, or terminate.
}

If you want this function to in turn call a method on an object, then unless the library provides some special mechanism to help you, you will just have to use one of the following techniques:

  • a namespace scope variable accessed by the callback, or

  • a dynamically generated callback.

C++ does not as of yet support the second approach, at all, so the first one is strongly indicated – if you want a callback on a method of an object.


EDIT: Sorry, I forgot to mention,

        the function declarations in the API documentation are syntactically invalid.

E.g. the documentation’s signature

void jack_set_info_function( void(*)(const char *) func );

simply won’t compile with a standard-conforming compiler. Not as C, and not as C++. It’s syntactically invalid in both languages.

Instead it should be

void jack_set_info_function( void(*func)(const char *) );

Since the documentation apparently is generated by DOxygen, it stands to reason that it's been generated from source code that compiles. If so then this is a bug in DOxygen, and a problem with the quality assurance of the library provider. However it might be a problem that lies solely with the library provider, or, I might be mistaken in the assumption that this is a C library?

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • This is a great answer, thank you for that information. The other function did provide an argument for an object pointer and thus I was able to use the method of a class. I just wanted to know if it was in any way possible to do the same thing with the `jack_set_error_function`. That clears things up, thanks again! – Tek Dec 24 '12 at 03:14
  • Although I did forget to mention. What certain types of problems can it bring me if I use static casting? You mention that it is a "formal" problem but you didn't describe the downsides of approaching it that way. Considering it works I may be able to live with any "problems" if they're minor enough. – Tek Dec 24 '12 at 03:17
  • Oh, the formal problem isn't about using `static_cast`, it's about using a `static` member function. Because a member function can't be `extern "C"` in standard C++. Mostly it doesn't matter in practice, but at least one compiler warns about it by default. – Cheers and hth. - Alf Dec 24 '12 at 03:21
  • The reason you can't use `reinterpret_cast` for the error callback is that you (presumably) don't control the pointer value passed to the callback. Most likely it's just a pointer to an error message, not a pointer to a C++ object. The type `char const*` *very strongly* indicates a pointer to error message string. Not knowing anything about the lifetime, I'd copy it to a `std::string` if it should be accessed later. E.g. if you post a GUI event. – Cheers and hth. - Alf Dec 24 '12 at 03:24
  • Sorry for editing the commentary, but it's a bit late and it took some time for me to understand what you meant (I *think* I understood it). – Cheers and hth. - Alf Dec 24 '12 at 03:26
  • No problem, yeah you answered my question pretty much. However I have no choice since there's no other way to call the class method in the argument without using `static`. I have to use the format `SoundClass::Method` in the C function as seen in my first example for it to work. – Tek Dec 24 '12 at 03:30
  • You can just use a free-standing function, as I wrote in the answer. If necessary make it a `friend` of the class. – Cheers and hth. - Alf Dec 24 '12 at 03:48
  • Right, I meant there's no way to use it with my class. Anyways free standing function it is. Thanks for your time and help. Cheers and happy holidays! ;D – Tek Dec 24 '12 at 03:59
  • Yes it looks like it's just a cosmetic bug, Jack is written in C99. If you look at the very top under the functions header the correct format is provided there. – Tek Dec 24 '12 at 08:03