Is it safe to pass int using XtPointer?

1.7k Views Asked by At

When defining a callback proc in Xt (for example XtTimerCallbackProc), client_data is specified as an XtPointer. Is it safe to pass an int via client_data, rather than an actual pointer, and cast it back inside the procedure?

For example:

void foo(void) {
   ...
   int data = 1;
   XtAppAddTimeout(app_context, 1000, timer_cb, data);
   ...
}

void timer_cb(XtPointer client_data, XtIntervalId *timer)
{
   int my_data = (int) client_data;
   ...
}
3

There are 3 best solutions below

2
On BEST ANSWER

It should be safe, but you should use an integer type that have the same size as a pointer.

The standard C99 type uintptr_t can be used for this purpose.

As per comments point out, int->ptr->int is not guaranteed by the use of this type. It should work more than often, but it is not as per specifications.

The alternative is to pass a pointer. If your app is single threaded, you might just do

static int data; and passs &data. If your app needs to be reentrant, then malloc an int.

As a matter of fact, I don't think the standard support int->ptr->int in any way.

1
On

Yes; the API uses a pointer because the size of this type is >= the size of an int on almost any computer/compiler combination, so you can use it to pass most things except double simply by casting.

0
On

I ran into this issue when trying to compile the Motif toggle_box.c example on a 64-bit Linux - Redhat 9.

The example code was passing an int as the XtPointer client_data parameter of a callback function.

The g++ compiler complained about loss of precision and I didn't seem to be getting the correct values.

I changed the code creating the widgets, changing int i; to unsigned long i;:

    unsigned long i;
    ...
    /* simply loop thru the strings creating a widget for each one */
    for (i = 0; i < XtNumber (strings); i++) {
        w = XtVaCreateManagedWidget (strings[i],
                     xmToggleButtonGadgetClass, toggle_box, NULL);
        XtAddCallback (w, XmNvalueChangedCallback,
                  XtCallbackProc)toggled, (XtPointer)i);
    }

I then changed the declaration of the toggled() callback subroutine to reflect this:

    void toggled(Widget widget, XtPointer client_data,
         XtPointer call_data)
    {
        //    int bit = (int)client_data;
        unsigned long bit = ((unsigned long)client_data);
    ...

This worked for me.