Sending data structure address via callback - Motif

This is a discussion on Sending data structure address via callback - Motif ; I'm trying to write some cleaner code. One of my goals is to eliminate global variables. The problem I have with this is how to access data across the program in the callbacks. I have sent individual variables successfully as ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: Sending data structure address via callback

  1. Sending data structure address via callback

    I'm trying to write some cleaner code. One of my goals is to eliminate
    global variables. The problem I have with this is how to access data
    across the program in the callbacks. I have sent individual variables
    successfully as the client data, but am having a massive problem sending
    the address of a data structure. I can send the data structure via it's
    address through the normal subroutines, but get strange pointers in my
    callbacks.

    for example:

    main()
    {
    data_structure data;
    ....
    call routine_a(&data)
    ....
    }

    routine_a(data)
    data_structure *data;
    {
    ....
    (*data).field_a = 123; <== This works fine;
    ....
    XtAddCallback(widget,
    XmNsingleSelectionCallback,
    select_callback,
    data);
    ....
    }

    extern void select_callback(w, data, call_data)
    Widget w;
    data_structure *data;
    XmListCallbackStruct *call_data;
    {

    (*data).field_a = 123; <== This does not work

    }

    When I run the debugger, the value of data (the pointer) changes from
    the XtAddCallback to the callback routine. For example, I checked the
    value of data before XtAddCallback, and it was 0x803c478. the value of
    &data was 0x803c3e0. When I got to the callback the value of data was
    0x80a7be0. I can't seem to get back to the original value I sent in the
    XtAddCallback routine.

    As I said, I have no problems sending a single integer or a string of
    characters. The problem is that I need more data than that for most
    callbacks. I could revert to global variables, but that goes against my
    better programming instincts.
    --
    God's Blessings and love

    Deacon Gary Meerschaert <'}}}}><

    Madison Heights, MI
    Archdiocese of Detroit

    Don't give up on your dreams.
    Wait a bit and they'll give up on you
    and you can start again without all of that guilt.

    Gary.meerschaert@gmail.com

  2. Re: Sending data structure address via callback

    When you are writing

    main() {
    data_structure data;
    ....
    call routine_a(&data)
    }

    you actually declare a local variable in the stack. The routine_a is
    called when main is active and occupies the memory. This is not
    necessary true for callbacks. They may not have access to that space

    Try instead to reserve (and release when is out of use) memory for your
    data. Do something like

    data_structure * data;

    data = calloc(.....);
    ....
    XtAddCallback(........, data);

    and pass the data pointer and not its address to callback. This will
    reserve memory in the heap. You may use the new operator in C++;

    Your problem then will be when to free that memory. Well, you need to
    do when the callback won't be called again (if there is such point in
    your program). Alternativelly the memory will be released when the
    program finishes.


  3. Re: Sending data structure address via callback

    Another minor point which will add clearness to your code

    Instead of
    (*data).field_a = 123;

    it is better to write
    data->field_a = 123;

    Perhaps you need to read more about pointers and structures from a
    standard C book (and possibly from C++ if you are intended to use
    operators like new and delete).


  4. Re: Sending data structure address via callback

    DVik wrote:
    > Another minor point which will add clearness to your code
    >
    > Instead of
    > (*data).field_a = 123;
    >
    > it is better to write
    > data->field_a = 123;
    >
    > Perhaps you need to read more about pointers and structures from a
    > standard C book (and possibly from C++ if you are intended to use
    > operators like new and delete).
    >

    It's a matter of taste. I have used these quite a bit, but find the ->
    to be a little less attractive. As I said, it's just a matter of taste
    and I have used both methods.

    --
    God's Blessings and love

    Deacon Gary Meerschaert <'}}}}><

    Madison Heights, MI
    Archdiocese of Detroit

    Don't give up on your dreams.
    Wait a bit and they'll give up on you
    and you can start again without all of that guilt.

    Gary.meerschaert@gmail.com

  5. Re: Sending data structure address via callback


    "Gary Meerschaert" wrote in message
    news:9KednbAaBcpne0zZnZ2dnUVZ_tGdnZ2d@wideopenwest .com...
    > I'm trying to write some cleaner code. One of my goals is to eliminate
    > global variables. The problem I have with this is how to access data
    > across the program in the callbacks. I have sent individual variables
    > successfully as the client data, but am having a massive problem sending
    > the address of a data structure. I can send the data structure via it's
    > address through the normal subroutines, but get strange pointers in my
    > callbacks.
    >
    > for example:
    >
    > main()
    > {
    > data_structure data;
    > ...
    > call routine_a(&data)
    > ...
    > }
    >
    > routine_a(data)
    > data_structure *data;
    > {
    > ...
    > (*data).field_a = 123; <== This works fine;
    > ...
    > XtAddCallback(widget,
    > XmNsingleSelectionCallback,
    > select_callback,
    > data);


    Error - select_callback is not yet known to the compiler.

    > ...
    > }
    >
    > extern void select_callback(w, data, call_data)
    > Widget w;
    > data_structure *data;
    > XmListCallbackStruct *call_data;
    > {
    >
    > (*data).field_a = 123; <== This does not work
    >
    > }


    The signature of a callback function is:
    void my_callback( Widget w, XtPointer client_data, XtPointer call_data );

    Thus the above should be:

    void select_callback( Widget w, XtPointer client_data, XtPointer call_data )
    {
    data_structure *data = (data_structure *)client_data;
    XmListCallbackStruct *cbs= (XmListCallbackStruct *)call_data;
    data->field_a = 123;
    }

    This avoids having to cast the function in the XtAddCallback call in order
    to
    keep the compiler from complaining about mismatched parameters (as long
    as you have included the forward declaration of the function).

    >
    > When I run the debugger, the value of data (the pointer) changes from the
    > XtAddCallback to the callback routine. For example, I checked the value of
    > data before XtAddCallback, and it was 0x803c478. the value of &data was
    > 0x803c3e0. When I got to the callback the value of data was 0x80a7be0. I
    > can't seem to get back to the original value I sent in the XtAddCallback
    > routine.
    >
    > As I said, I have no problems sending a single integer or a string of
    > characters. The problem is that I need more data than that for most
    > callbacks. I could revert to global variables, but that goes against my
    > better programming instincts.
    > --
    > God's Blessings and love
    >
    > Deacon Gary Meerschaert <'}}}}><
    >
    > Madison Heights, MI
    > Archdiocese of Detroit
    >
    > Don't give up on your dreams.
    > Wait a bit and they'll give up on you
    > and you can start again without all of that guilt.
    >
    > Gary.meerschaert@gmail.com


    In the callback function, try setting field_a to some different value
    than it was set before. Then in the debugger, when the callback is
    called and the value set, back out to main() and examine the structure.

    --
    Fred L. Kleinschmidt
    Boeing Associate Technical Fellow
    Technical Architect, Software Reuse Project



  6. Re: Sending data structure address via callback

    Fred Kleinschmidt wrote:
    > "Gary Meerschaert" wrote in message
    > news:9KednbAaBcpne0zZnZ2dnUVZ_tGdnZ2d@wideopenwest .com...
    >
    >>I'm trying to write some cleaner code. One of my goals is to eliminate
    >>global variables. The problem I have with this is how to access data
    >>across the program in the callbacks. I have sent individual variables
    >>successfully as the client data, but am having a massive problem sending
    >>the address of a data structure. I can send the data structure via it's
    >>address through the normal subroutines, but get strange pointers in my
    >>callbacks.
    >>
    >>for example:
    >>
    >>main()
    >>{
    >> data_structure data;
    >>...
    >> call routine_a(&data)
    >>...
    >>}
    >>
    >>routine_a(data)
    >> data_structure *data;
    >>{
    >>...
    >> (*data).field_a = 123; <== This works fine;
    >>...
    >> XtAddCallback(widget,
    >> XmNsingleSelectionCallback,
    >> select_callback,
    >> data);

    >
    >
    > Error - select_callback is not yet known to the compiler.
    >
    >
    >>...
    >>}
    >>
    >>extern void select_callback(w, data, call_data)
    >> Widget w;
    >> data_structure *data;
    >> XmListCallbackStruct *call_data;
    >>{
    >>
    >> (*data).field_a = 123; <== This does not work
    >>
    >>}

    >
    >
    > The signature of a callback function is:
    > void my_callback( Widget w, XtPointer client_data, XtPointer call_data );
    >
    > Thus the above should be:
    >
    > void select_callback( Widget w, XtPointer client_data, XtPointer call_data )
    > {
    > data_structure *data = (data_structure *)client_data;
    > XmListCallbackStruct *cbs= (XmListCallbackStruct *)call_data;
    > data->field_a = 123;
    > }
    >
    > This avoids having to cast the function in the XtAddCallback call in order
    > to
    > keep the compiler from complaining about mismatched parameters (as long
    > as you have included the forward declaration of the function).
    >
    >
    >>When I run the debugger, the value of data (the pointer) changes from the
    >>XtAddCallback to the callback routine. For example, I checked the value of
    >>data before XtAddCallback, and it was 0x803c478. the value of &data was
    >>0x803c3e0. When I got to the callback the value of data was 0x80a7be0. I
    >>can't seem to get back to the original value I sent in the XtAddCallback
    >>routine.
    >>
    >>As I said, I have no problems sending a single integer or a string of
    >>characters. The problem is that I need more data than that for most
    >>callbacks. I could revert to global variables, but that goes against my
    >>better programming instincts.
    >>--
    >>God's Blessings and love
    >>
    >>Deacon Gary Meerschaert <'}}}}><
    >>
    >>Madison Heights, MI
    >>Archdiocese of Detroit
    >>
    >>Don't give up on your dreams.
    >>Wait a bit and they'll give up on you
    >>and you can start again without all of that guilt.
    >>
    >>Gary.meerschaert@gmail.com

    >
    >
    > In the callback function, try setting field_a to some different value
    > than it was set before. Then in the debugger, when the callback is
    > called and the value set, back out to main() and examine the structure.
    >

    Thanks. I tried to skip the step of
    data = (data__struct *)client_data;
    I guess that there is a good reason for it. It seemed useless (and not
    included in the reference books) when passing something like an integer.
    Thanks for the help.

    --
    God's Blessings and love

    Deacon Gary Meerschaert <'}}}}><

    Madison Heights, MI
    Archdiocese of Detroit

    Don't give up on your dreams.
    Wait a bit and they'll give up on you
    and you can start again without all of that guilt.

    Gary.meerschaert@gmail.com

  7. Re: Sending data structure address via callback

    Gary Meerschaert wrote:
    > Fred Kleinschmidt wrote:

    [snip]

    >>
    >>
    >> In the callback function, try setting field_a to some different value
    >> than it was set before. Then in the debugger, when the callback is
    >> called and the value set, back out to main() and examine the structure.
    >>

    > Thanks. I tried to skip the step of
    > data = (data__struct *)client_data;
    > I guess that there is a good reason for it. It seemed useless (and not
    > included in the reference books) when passing something like an integer.
    > Thanks for the help.
    >


    Personnally, I avoid using client_data as much as possible. Instead, I
    install in XmNclientData of a widget a pointer to a list of key/value
    pairs. My keys are tags but strings are OK too. The values are various
    malloced structs. When looking for a key on a widget, if not found I try
    on the parent widget.

    Cheers,
    --
    Michel Bardiaux
    R&D Director
    T +32 [0] 2 790 29 41
    F +32 [0] 2 790 29 02
    E mailto:mbardiaux@mediaxim.be

    Mediaxim NV/SA
    Vorstlaan 191 Boulevard du Souverain
    Brussel 1160 Bruxelles
    http://www.mediaxim.com/

+ Reply to Thread