callback functions and static_cast for wrapping class methods - c++

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.

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?

Related

Using callbacks in C++

I'm working on a project in C++, but at some point in the application it fails and generates a core dump. The application uses a couple of classes, which for the purposes here I'm concentrating on one of the classes, which I'm calling A, and is instantiated as object a. This has a large number of member functions, of which at the moment only a few are being used, but one of these generates a log to produce diagnostics to be used for debugging. I want to use this to find out why the application is failing.
The project is to put together code that invokes the various member functions, and although I have access to the source code and some limited documentation, none of the code can be changed, with all changes being in the code that makes use of the classes and invokes the member functions. The member function in question is:
void enable_log (log_callback callback, void * user_data = nullptr)
where the 1st argument callback contains the message and 2nd argument is optional. For now it can be set to nullptr, so would be invoked as:
a.enable_log(callback, nullptr);
From this documentation it's not at all clear what exactly callback is. However, in looking at the source code this is:
using log_callback = void (*)(const std::string& message, void* user_data);
in a header file, where log_callback is an alias for const std::string& if I understand this correctly.
I already have dummy classes on a platform using Visual Studio 2019 with some test member functions to simulate invoking the member functions on a remote Linux server, but I'm unable to find a way of making use of the member function above. I added the test member function to the dummy class as follows:
void enable_log(const std::string& callback, void* user_data = nullptr) {
callback = "ABCD";
}
which is supposed to generate a test string which is returned, such that in the real application this string will have diagnostic information that will be written to a file. However, the "=" is an error.
The idea is that in the main function an empty string will be declared, then enable_log() should populate this string, which can be printed out.
I've spent some time looking at various resources, including Stackoverflow, but I cannot find a way of returning a string with the information that can be printed out. I need a simple way to simulate this, and as I said above, I must not change the source code of the real member function, so the simulated member function has to produce a string in the same way. How is this done? Some advice would be appreciated.
Callback, in simple words, is some function that will be called later at some point. Example:
void callback_fn(int a);
using callback_t = (void)(*)(int a);
void some_func(callback_t);
You can use some_func() like so:
some_func(callback_fn);
Full example here: https://godbolt.org/z/ET3GhfYrv
For your usecase the parameters of the callback are slightly different. Here's how to read the syntax:
using log_callback = // this just creates an alias for whatever is on the right handside
void // the return type of the "callable" should be void
(*) // this tells us that it is a function pointer
(const std::string& message, void* user_data) // These are the arguments the callable takes. It is a "std::string" and a "void *"
To use this, just create a free function with the same signature:
void callable(const std::string &msg, void *userData = nullptr)
{
// msg is the data sent by the function. use it in whatever way
// you want.
std::cout << msg << '\n';
}
// Pass it to the enable_log
enable_log(callable);

Pointer problem using functions from non-object API in objects

I am writing some C++ code to get data from a SDR (software defined radio) and analyse it using an FFT library (FFTW3). The software uses an API (SDR_play_API and its DLL). I am trying to include the API functionality into an object. The library comes with a non-object based example program.
The IDE I am using is VS2105.
Three of the functions are callbacks to handle events from the hardware. The address of the callback functions that handle these events are passed to the API through a structure. I include the relevant code snippets from the example program, the header files and my own code after a description of the problem.
Though I have been on some C++ training - and taught others the basics - I am far from an expert and the problem goes beyond my understanding of pointers and objects.
The problem I have is one that has been discussed before on Stack Exchange. It is a problem of pointers to member functions.
The simple solution would seem to be to make the functions STATICs. However that causes problems because of some of the variables used in these functions. Without making them static then the compiler complains and if I make them static the linker complains because there is no matching definition for static variables in the library.
I have looked through Stack Exchange tried the solutions suggested but I can't seem to make any of them work - I get compiler errors.
So I feel ideally I just want to pass the pointers to the member functions to API through the structure ... but I have tried all sorts of variations on syntax without success. Can anyone help?
The API comes with an example program that does not use objects. So before I reveal my attempts to use the functions in an object, here is the code from the example program. First I will show where it assigns the location of the functions to the members of the structure, then I will include the structure definitions etc from the header file.
First then, the assignment:
// Assign callback functions to be passed to sdrplay_api_Init()
cbFns.StreamACbFn = StreamACallback;
cbFns.StreamBCbFn = StreamBCallback;
cbFns.EventCbFn = EventCallback;
Here, from the header file that comes with the API, is the definition of the structure
{
sdrplay_api_StreamCallback_t StreamACbFn;
sdrplay_api_StreamCallback_t StreamBCbFn;
sdrplay_api_EventCallback_t EventCbFn;
} sdrplay_api_CallbackFnsT;
and here, again from the header file that comes with the API is the definition of the data types - you can see the these are function pointers
typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
here is one of the call back function declarations
void StreamACallback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext)
{
...
}
So that all works fine and compiles - but it that works in a non-object scenario.
However when I make the functions a member of a class then I get errors. I have tried the following variations without success. Can someone please point me in the right direction - if I had had hair by now I wouldn't have anymore cause it would be on the floor all around me in clumps.
function definition:
void sdr_object::StreamACallback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext)
{
...
}
Unsuccessful attempts to assign to structure include (including compiler error)
cbFns.StreamACbFn = this->StreamACallback;//"non standard syntax: use '&' to create a pointer to the member"
//cannot convert from 'void (__cdecl sre_object::*)(...) to sdrplay_api_StreanCallback_t
cbFns.StreamACbFn = &this->StreamACallback;//'&': illegal operation on bound member function experssion
cbFns.StreamACbFn = this->sdr_object::StreamACallback; //"non standard syntax: use '&' to create a pointer to the member"
//cannot convert from 'void (__cdecl sre_object::*)(...) to sdrplay_api_StreanCallback_t
cbFns.StreamACbFn = &this->sdr_object::StreamACallback; //'&': illegal operation on bound member function experssion
Any wisdom will e received most gratefully. (How to do it will be received even more gratefully ...!)
This answer comes with many thanks to Igor Tandetnik who suggested the solution in comments above.
Igor wrote "Make your callbacks static member functions. Pass this pointer for cbContext parameter to sdrplay_api_Init - you get that same pointer back in the callback. Now the callback can do static_cast<MyClass*>(cbContext)->memberFunction(params); . The actual logic can now be implemented in a non-static member function; the static one just serves as a glue between C++ implementation and C API"
My implementation of that is as follows:
Add to the class declaration in the header file an intermediary "glue" function for each event handler e.g.:
static void sdr_object::StreamACallback_static(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext)
{
static_cast<sdr_object*>(cbContext)->StreamACallback(xi, xq, params, numSamples, reset, cbContext);
};
For the function above, the pointer that is handed to the API then becomes
cbFns.StreamACbFn = this->StreamACallback_static;
In my particular example, I then had to do the same for the other two functions.
I did not have to change any other existing code.
Again, many thanks to Igor for the answer - I hope I have implemented it as he intended ... that said, what I have described works, so I imagine I have!

Bad practice to call static function from external file via function pointer?

Consider the following code:
file_1.hpp:
typedef void (*func_ptr)(void);
func_ptr file1_get_function(void);
file1.cpp:
// file_1.cpp
#include "file_1.hpp"
static void some_func(void)
{
do_stuff();
}
func_ptr file1_get_function(void)
{
return some_func;
}
file2.cpp
#include "file1.hpp"
void file2_func(void)
{
func_ptr function_pointer_to_file1 = file1_get_function();
function_pointer_to_file1();
}
While I believe the above example is technically possible - to call a function with internal linkage only via a function pointer, is it bad practice to do so? Could there be some funky compiler optimizations that take place (auto inline, for instance) that would make this situation problematic?
There's no problem, this is fine. In fact , IMHO, it is a good practice which lets your function be called without polluting the space of externally visible symbols.
It would also be appropriate to use this technique in the context of a function lookup table, e.g. a calculator which passes in a string representing an operator name, and expects back a function pointer to the function for doing that operation.
The compiler/linker isn't allowed to make optimizations which break correct code and this is correct code.
Historical note: back in C89, externally visible symbols had to be unique on the first 6 characters; this was relaxed in C99 and also commonly by compiler extension.
In order for this to work, you have to expose some portion of it as external and that's the clue most compilers will need.
Is there a chance that there's a broken compiler out there that will make mincemeat of this strange practice because they didn't foresee someone doing it? I can't answer that.
I can only think of false reasons to want to do this though: Finger print hiding, which fails because you have to expose it in the function pointer decl, unless you are planning to cast your way around things, in which case the question is "how badly is this going to hurt".
The other reason would be facading callbacks - you have some super-sensitive static local function in module m and you now want to expose the functionality in another module for callback purposes, but you want to audit that so you want a facade:
static void voodoo_function() {
}
fnptr get_voodoo_function(const char* file, int line) {
// you tagged the question as C++, so C++ io it is.
std::cout << "requested voodoo function from " << file << ":" << line << "\n";
return voodoo_function;
}
...
// question tagged as c++, so I'm using c++ syntax
auto* fn = get_voodoo_function(__FILE__, __LINE__);
but that's not really helping much, you really want a wrapper around execution of the function.
At the end of the day, there is a much simpler way to expose a function pointer. Provide an accessor function.
static void voodoo_function() {}
void do_voodoo_function() {
// provide external access to voodoo
voodoo_function();
}
Because here you provide the compiler with an optimization opportunity - when you link, if you specify whole program optimization, it can detect that this is a facade that it can eliminate, because you let it worry about function pointers.
But is there a really compelling reason not just to remove the static from infront of voodoo_function other than not exposing the internal name for it? And if so, why is the internal name so precious that you would go to these lengths to hide that?
static void ban_account_if_user_is_ugly() {
...;
}
fnptr do_that_thing() {
ban_account_if_user_is_ugly();
}
vs
void do_that_thing() { // ban account if user is ugly
...
}
--- EDIT ---
Conversion. Your function pointer is int(*)(int) but your static function is unsigned int(*)(unsigned int) and you don't want to have to cast it.
Again: Just providing a facade function would solve the problem, and it will transform into a function pointer later. Converting it to a function pointer by hand can only be a stumbling block for the compiler's whole program optimization.
But if you're casting, lets consider this:
// v1
fnptr get_fn_ptr() {
// brute force cast because otherwise it's 'hassle'
return (fnptr)(static_fn);
}
int facade_fn(int i) {
auto ui = static_cast<unsigned int>(i);
auto result = static_fn(ui);
return static_cast<int>(result);
}
Ok unsigned to signed, not a big deal. And then someone comes along and changes what fnptr needs to be to void(int, float);. One of the above becomes a weird runtime crash and one becomes a compile error.

Is this C callback safe with C++ objects?

My purpose is to call some C function from my C++ code and pass some C++ objects.
In fact I am using a integration routine from the GSL libray(written in C), see this link,
My code snippet:
// main.cpp
#include <stdio.h>
#include <gsl/gsl_integration.h>
#include <myclass.h>
/* my test function. */
double testfunction ( double x , void *param ) {
myclass *bar=static_cast<myclass*>(param);
/*** do something with x and bar***/
return val;
}
int main ( int argc , char *argv[] ) {
gsl_function F; // defined in GSL: double (* function) (double x, void * params)
/* initialize.*/
gsl_integration_cquad_workspace *ws =
gsl_integration_cquad_workspace_alloc( 200 ) ;
/* Prepare test function. */
myclass foo{}; // call myclass constructor
F.function = &testfunction;
F.params = &foo;
/* Call the routine. */
gsl_integration_cquad( &F, 0.0,1.0,1.0e-10,1.0e-10,ws, &res,&abserr,&neval);
/* Free the workspace. */
gsl_integration_cquad_workspace_free( ws );
return 0;
}
In my case, direct calling gsl_integration_cquad seems OK, provided the header includes sth like "ifdef __cplusplus", my concern is about the callback F,originally defined in C, am I allowed to pass the testfunction and also the C++ foo object in this way ? .
or is there any better way to do this kind of stuff, maybe overloading and use a functor?
P.S. Am I allowed to do exeption handling within the callback function? (use try catch inside "testfunction"). It works in my case but not sure if it's legal.
I'm not familiar with the library in question, but in general,
when passing a pointer to a callback and a void* to
a C routine, which will call the callback back with the void*,
there are two things you need to do to make it safe:
The function whose address you pass must be declared extern "C".
You'll get away with not doing this with a lot of compilers, but
it isn't legal, and a good compiler will complain.
The type you convert to the void* must be exactly the same
type as the type you cast it back to in the callback. The
classic error is to pass something like new Derived to the
C function, and cast it back to Base* in the callback. The
round trip Derived*→void*→Base* is undefined
behavior. It will work some of the time, but at other times, it
may crash, or cause any number of other problems.
And as cdhowie pointed out in a comment, you don't want to
allow exceptions to propagate accross the C code. Again, it
might work. But it might not.
For the exact example you posted, the only thing you need to do
is to declare testfunction as extern "C", and you're all
right. If you later start working with polymorphic objects,
however, beware of the second point.
You can use
myclass *bar=static_cast<myclass*>(param);
with void*.
If you meant something like transporting a c++ class pointer through a c callback's void* pointer, yes it's safe to do a static_cast<>.
There's no kind of losing c++ specific attributes of this class pointer, when passed through c code. Though passing a derived class pointer, and static casting back to the base class, won't work properly as #James Kanze pointed out.
The void* will likely just be passed trough by the C library without looking at the pointed-to data, so it's not a problem if this contains a C++ class. As log as you cast the void* to the correctly there shouldn't be any problems.
To make sure the callback function itself is compatible, you can declare it as extern "C". Additionally you should make sure that no exceptions are thrown from the callback function, since the C code calling the callback won't expect those.
All together I would split up the code into one function that does the real work and another function that is used as the callback and handles the interface with the C library, for example like this:
#include <math.h>
double testfunction ( double x ,myclass *param ) {
/*** do something with x and bar***/
return val;
}
extern "C" double testfunction_callback ( double x , void *param ) {
try {
myclass *bar=reinterpret_cast<myclass*>(param);
return testfunction(x, bar);
}
catch(...) {
std::cerr << "Noooo..." << std::endl;
return NAN;
}
}

How to pass a char* from C to CPP?

A little background:
I've got a library of C code that is part of larger system (all C). For this particular part of the C library a GUI has to be created which allows users to play around with the options. For the GUI I've chosen QT, since cross-platform support is desired.
I'm using Eclipse and MinGW as IDE and compiler (but I think the question is more language than compiler specific?).
With QT I've created a widget that holds a pointer to a struct implemented in C that contains pointers to several functions that perform the logic of the C library.
//QTWidget.cpp
extern "C" {
#include "c-src/CLogic.h"
//extern char* textHelper;
}
QTWidget::QTWidget(QWidget *parent)
{
//rtw is a struct that contains a function pointer to a member of QTWidget
this->rtw.displayText = &QTWidget::displayText;
this->clogic = CLogic_getInstance(&rtw);
}
//Public SLOT, connected to a button's clicked SIGNAL
void QTWidget::buttonClicked()
{
this->clogic->buttonClicked();
}
void QTWidget::displayText(char *text, int position)
{
//I've tried creating a QString from the char*, but this does not work at all.
//ui.textItem->setText(textHelper);
ui.textItem->setText(text);
}
When the user presses a button in the GUI, the method QTWidget::buttonClicked() is called, which tells the C library to do something. Note the the CLogic struct has a reference to the the QTWidget in the form of a struct RefToWidget which holds a function pointer.
//CLogic.c
static CLogic instance;
void CLogic_buttonClicked()
{
//I've tried several variants here, such as making a global
//char* textHelper = "Hello World";
//that is referenced by using the "extern" keyword in the CPP file above.
instance.rtw->displayText("Hello World", 1);
}
CLogic* CLogic_getInstance(RefToWidget *rtw)
{
instance.rtw = rtw;
instance.buttonClicked = &CLogic_buttonClicked();
}
When debugging this program, I find that all the function calls are executed as intended (when I press a button, the QT slot buttonClicked() is called, the CLogic_buttonClicked() is called, which calls the QTWidget::displayText() as planned, but in this last call the parameters are invalid. The char* text points to 0x1 and claims to be pointing to memory out of bounds, while the int position looks like some random number (uninitialized).
How do I pass this data from C to CPP?
EDIT #Luccas Matteis:
#ifdef __cplusplus
#include "QTWidget.h"
extern "C" {
#endif
struct RefToWidget{
#ifdef __cplusplus
void (QTWidget::*displayLine)(char* text, int lineNumber);
#else
void (*displayLine)(char* text, int lineNumber);
#endif
};
typedef struct RefToWidget RefToWidget;
#ifdef __cplusplus
}
#endif
As said above the function calls behave as expected, but the data is not passed "correctly" (even though that when I look at it, the code seems a bit... weird... ;))
Your problem is not passing the char * from C to C++ but calling a C++ function from C. I presume that CLogic.c is compiled as a C library? If not, can you rename it to CLogic.cpp or use a compiler switch to force it to be compiled as C++ even though it has a C file extension?
If you want a C++ GUI on a C library/system, you need to use proper Model-View-Controller logic. Here the C++ code is the View and the Controller while the C code is the Model (as best as I can tell from your description). You need to make it so you set and get data from the model but the model never calls the View or Controller as you are trying to do.
Think about what you are REALLY trying to do. If you just want to display a static string when the button is pressed, why go to the bother of calling into CLogic.c? If you want to display a string that depends upon the state of the CLogic instance then instead do something like:
void QTWidget::buttonClicked()
{
char *display_text = this->clogic->get_button_click_text();
ui.textItem->setText(display_text);
}
I guess the problem is that the structure holds a pointer to a member function. The member function probably expects the first parameter to be 'this' - the object it refers to. So, in fact what you are seeing in debug as text is the second parameter.
A 'solution' would probably be to do something like "instance.rtw->displayText(instance.rtw, "Hello World", 1)", but have no idea if it is portable etc.
Edit: Saying it explicitly: the 'solution' stated above is just to try and check if this is the problem. As the comments are saying this is a horrible hack that might not work even on the same compiler.
I don't think that you should call a C++ method from C. Normally you need to go through a static method that dereferences a pointer argument