为什么在 Motif 中使用 PushButton 简单回调时会收到此警告?

Why do I get this warning when using a PushButton simple callback in Motif?

我正在尝试无误地编译这段代码摘录:

#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/List.h>

/* FUNCTION DECLARATION */
void add_printers();
void add_printer(char *printer_name);
void add_command_groups(char *printer_name);
void read_printer_file(char *printer_name);
Widget make_menu_item(char *item_name, Widget menu);
void select_printer(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *call_data);

/* XT/XM RELATED VARIABLES */
XtAppContext context;
XmStringCharSet char_set = XmSTRING_DEFAULT_CHARSET;

/* WIDGETS */
Widget toplevel; 
Widget form;

Widget printer_pulldown_menu;
Widget printer_option_menu;
Widget printer_option_item[100];
int printer_menu_items = 0;

Widget command_group_list;
Widget command_list;

int main(int argc, char *argv[]) {

    Arg al[10];
    int ac;

    /* CREATE TOP SHELL WIDGET */
    toplevel = XtAppInitialize(&context, "", NULL, 0, &argc, argv, NULL, NULL, 0);

    /* RESIZE TOP LEVEL*/
    ac = 0;
    XtSetArg(al[ac], XmNheight, 900); ac++;
    XtSetArg(al[ac], XmNwidth, 600); ac++;
    XtSetValues(toplevel, al, ac);

    /* CREATE FORM MANAGER WIDGET */
    form = XmCreateForm(toplevel, "form", al, ac);
    XtManageChild(form);

    /* SELECT PRINTER PULLDOWN */
    ac = 0;
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
    printer_pulldown_menu= XmCreatePulldownMenu(form, "printer_pulldown_menu", al, ac);
    ac = 0;
    XtSetArg(al[ac], XmNsubMenuId, printer_pulldown_menu); ac++;
    XtSetArg(al[ac], XmNlabelString, XmStringCreate("Printer", char_set)); ac++;
    
    /* SELECT PRINTER OPTIONS */
    printer_option_menu = XmCreateOptionMenu(form, "printer_option_menu", al, ac);
    add_printers();
    XtManageChild(printer_option_menu);

    /* COMMAND GROUP LIST */
    ac = 0;
    XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
    XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
    XtSetArg(al[ac], XmNtopWidget, printer_option_menu); ac++;
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
    XtSetArg(al[ac], XmNbottomPosition, 50); ac++;
    command_group_list = XmCreateScrolledList(form, "command_group_list", al, ac);
    XtManageChild(command_group_list);
    
    /* COMMAND LIST */
    ac = 0;
    XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
    XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
    XtSetArg(al[ac], XmNtopWidget, command_group_list); ac++;
    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
    XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
    command_list = XmCreateScrolledList(form, "command_list", al, ac);
    XtManageChild(command_list);

    /* REALIZE TOPLEVEL */
    XtRealizeWidget(toplevel);
    XtAppMainLoop(context);

    return 0;

}

/* THIS FUNCTION READS FILES UNDER /etc/xcmdprinter AND ADDS EACH PRINTER TO THE MENU */
void add_printers() {

    DIR *dd;
    struct dirent *entry;

    dd = opendir("/etc/xcmdprinter");
    while((entry = readdir(dd))!=NULL) {

        /* PROCESS ONLY FILES AND SYMBOLIC LINKS */
        int i = 0;
        if(entry->d_type == DT_REG || entry->d_type == DT_LNK) {

                /* OPEN FILE AND READ LINE BY LINE */
                add_printer(entry->d_name);

        }
    }
    closedir(dd);

}

void read_printer_file(char *printer_name) {
}

void add_printer(char *printer_name) {

    if(printer_menu_items==100) {
        fprintf(stderr, "ERROR: Maximum number of available printers is 100\n");
        exit(1);
    }
    printer_option_item[printer_menu_items] = make_menu_item(printer_name, printer_pulldown_menu);
    printer_menu_items++;
    
}

Widget make_menu_item(char *item_name,  Widget menu) {

    int ac;
    Arg al[10];
    Widget item;

    ac = 0;
    XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR(item_name, char_set)); ac++;
    item = XmCreatePushButton(menu, item_name, al, ac);
    XtManageChild(item);
    XtAddCallback(item, XmNactivateCallback, select_printer, NULL);
    XtSetSensitive(item, True);
    return(item);

}

void select_printer(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *call_data) {    
    printf("BUTTON SELECTED\n");
}

void add_command_groups(char *printer_name) {
}

这是生成文件:

xcmdprinter:        xcmdprinter.o 
            cc -std=c89 xcmdprinter.o -o xcmdprinter -L/usr/local/lib -I/usr/local/include -lXm -lXt -lX11

xcmdprinter.o:      xcmdprinter.c
            cc -g -std=c89 -c xcmdprinter.c -o xcmdprinter.o -I/usr/local/include

clean:
            rm */*.o
            rm xcmdprinter
            rm *.core

然而,我在为选项菜单项选择实现回调时收到以下警告,我正在努力理解为什么会生成此警告以及如何解决它。

cc -g -std=c89 -c xcmdprinter.c -o xcmdprinter.o -I/usr/local/include
xcmdprinter.c:154:43: warning: incompatible pointer types passing 'void (Widget, XtPointer, XmPushButtonCallbackStruct *)' (aka 'void (struct _WidgetRec *, void *, XmPushButtonCallbackStruct *)') to parameter of
      type 'XtCallbackProc' (aka 'void (*)(struct _WidgetRec *, void *, void *)') [-Wincompatible-pointer-types]
        XtAddCallback(item, XmNactivateCallback, select_printer, NULL);
                                                 ^~~~~~~~~~~~~~
/usr/local/include/X11/Intrinsic.h:1247:35: note: passing argument to parameter here
    XtCallbackProc      /* callback */,
                                      ^
1 warning generated.

select_printer 的最后一个参数类型与 XtAddCallback 预期的回调类型不匹配。

select_printer 函数有一个 XmPushButtonCallbackStruct * 参数,而回调应该有一个 void * 参数。

我建议的修复方法是将 select_printer 的最后一个参数更改为 void *,然后在 select_printer 中将参数转换为正确的类型。喜欢:

// Prototype declaration
void select_printer(Widget w, XtPointer client_data, XtPointer *call_data);

// ...

// Function definition
void select_printer(Widget w, XtPointer client_data, XtPointer *call_data_voidp)
{
    XmPushButtonCallbackStruct *call_data = (XmPushButtonCallbackStruct *) call_data_voidp;

    // ...
}