I have written a multi-threaded program that works, but throws warnings at compile-time.
The header file contains the definition of a struct which contains data, as well as the thread function prototype:
//=============main.h=============
// Main data structure definition
typedef struct _SPSData SPSData;
struct _SPSData {
GtkWidget *main_window;
GtkWidget *menubar1;
GtkWidget *view;
GtkWidget *parent; // Pointer to parent that spawned an error. e.g., data->menubar1, data->main_window, or data->traceroute_window
char *error_text; // String to hold error messages.
char *warning_text; // String to hold warning messages.
etc.
};
// Thread function prototype
int ipv4_send (SPSData *);
The thread function to be started by g_thread_new() looks like:
//==========ipv4_send.c=============
int ipv4_send (SPSData *data)
{
some error detection
if error {
return (EXIT_FAILURE);
}
Send ipv4 stuff.
return (EXIT_SUCCESS);
}
And there's a callback from the UI which invokes ipv4_send() via g_thread_new():
//==========callbacks.c=======
// Send packet(s)
int on_button1_clicked (GtkButton *button1, SPSData *data)
{
(void) button1; // This statement suppresses compiler warning about unused parameter.
GThread *thread;
// Spawn thread to send IPv4 packet(s).
thread = g_thread_new ("ipv4_send", (GThreadFunc) ipv4_send, data);
if (! thread) {
fprintf (stderr, "Error: Unable to create new thread for ipv4_send() in on_button1_clicked().\n");
exit (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}
On compilation, I receive the warning:
callbacks.c: In function ‘on_button1_clicked’:
callbacks.c:3846:41: warning: cast between incompatible function types from ‘int (*)(SPSData *)’ {aka ‘int (*)(struct _SPSData *)’} to ‘void * (*)(void *)’ [-Wcast-function-type]
3846 | thread = g_thread_new ("ipv4_send", (GThreadFunc) ipv4_send, data);
Should the thread function be defined as follows?
==========ipv4_send.c=============
int *ipv4_send (SPSData *data)
{
etc.
with corresponding change to the prototype:
// Thread function prototype
int *ipv4_send (SPSData *);
I don't know how to implement that, as my return statements would be incorrect.
In summary, I don't know how to make my function conform to the expected GThreadFunc typing.
Here is the answer as I interpreted what Cheatah said in the comments. This works perfectly and the compiler is no longer throwing warnings.
The header file contains the definition of a struct which contains data, as well as the thread function prototype:
//=============main.h=============
// Main data structure definition
typedef struct _SPSData SPSData;
struct _SPSData {
GtkWidget *main_window;
GtkWidget *menubar1;
GtkWidget *view;
GtkWidget *parent; // Pointer to parent that spawned an error. e.g., data->menubar1, data->main_window, or data->traceroute_window
char *error_text; // String to hold error messages.
char *warning_text; // String to hold warning messages.
etc.
};
// Thread function prototype (consistent with GThreadFunc).
void * ipv4_send (void *);
The thread function to be started by g_thread_new() looks like:
//==========ipv4_send.c=============
void *ipv4_send (void *pointer)
{
struct _SPSData *data;
data = (SPSData *) pointer;
some error detection
if error {
return (pointer);
}
Send ipv4 stuff.
return (pointer);
}
And there's a callback from the UI which invokes ipv4_send() via g_thread_new():
//==========callbacks.c=======
// Send packet(s)
int on_button1_clicked (GtkButton *button1, SPSData *data)
{
(void) button1; // This statement suppresses compiler warning about unused parameter.
GThread *thread;
// Spawn thread to send IPv4 packet(s).
thread = g_thread_new ("ipv4_send", (GThreadFunc) ipv4_send, data);
if (! thread) {
fprintf (stderr, "Error: Unable to create new thread for ipv4_send() in on_button1_clicked().\n");
exit (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}
Thank you, Cheatah!