LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with ATTR_CALLBACK_DATA attribute. Changes when received by routine.

Solved!
Go to solution

Using LabWindows/CVI 2013, PC (Windows XP)

 

I'm passing a pointer to a calloc-generated memory block so that when I call an instrument callback certain parameters are available:

 

ViStatus PLOT_JPlot (struct Level1DataBlock *L1DB_p) {
    G_PanelInfo_p = CreatePanelInfoBlock (L1DB_p, PANEL_JPLOT); //a rather complicated routine that uses calloc to create and than initializes a bunch of data structures.

     ...

    iHandle = LoadPanelEx (0, JPlotPanel_UIR_file, JPLOT, __CVIUserHInst); //load the panel from the UIR file

    ....
    status = SetPanelAttribute (iHandle, ATTR_CALLBACK_DATA, (void *)G_PanelInfo_p); //load the pointer into the callback data area for this panel
    ....

    status = CallCtrlCallback (iHandle, JPLOT_CURSORBUTTON, EVENT_COMMIT, 0, 0, 0);

    ....

}

 

which results in a call to

int CVICALLBACK CB_JPlotCursorToggle (int panel, int control, int event,    void *callbackData, int eventData1, int eventData2) {

    struct PanelInfoConst *G_PanelInfo_p = NULL;
    ....
    switch (event) {
    case EVENT_COMMIT:

            GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &panelcallbackData_p);
            G_PanelInfo_p = (struct PanelInfoConst *)panelcallbackData_p;              //wrong pointer here. 

     ...

    }

}

 

G_PanelInfo_p ends up being a pointer to somewhere in hyperspace, and I get a memory error - it's pointing to somewhere outside of the whole process' memory space.

 

Except that this same bit works perfectly for another window. The only difference is that the other window is actually being displayed on the screen before I call "CallCtrlCallback ()" and with this window it hasn't actually displayed yet.

 

The memory block is freed when the window is closed.

 

Keeping in mind this other post:

http://forums.ni.com/t5/LabWindows-CVI/InstallWinMsgCallback-changes-the-panel-s-ATTR-CALLBACK-DATA/...

should I be using the chained-callback feature?

 

Oh, and while I'm at it, what's supposed to show up in the " void *callbackData" parameter of the callback function? It ends up NULL; I would think that the ATTR_CALLBACK_DATA entry would show up there.

0 Kudos
Message 1 of 8
(4,684 Views)

Some further information.

the routine CB_JPlotCursorToggle is the callback for a control that's in the JPLOT panel. Note that I'm calling "GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &panelcallbackData_p);" on the "panel" parameter that's passed in when the callback is called via CallCtrlCallback. 

 

If I call "GetPanelAttribute (panel, ATTR_CALLBACK_DATA....) from a function that's directly connected to the panel, e.g. the panel callback, I get the proper value for panelcallbackData_p. This is what I'm doing on the other routine, which works.

0 Kudos
Message 2 of 8
(4,673 Views)

After further experimentation, it seems that:

if I call "GetPanelAttribute (panel, ATTR_CALLBACK_DATA....) from the panel callback, I get the right value.

If I call it from anywhere else, namely from the callback of a control, I do not get the right value, even though the "panel" handle parameter is correct.

0 Kudos
Message 3 of 8
(4,667 Views)

How is your 'panelcallbackdata_p' defined in both cases?



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 4 of 8
(4,658 Views)

It's a (void *).

I forget why I did that, but I get the same result if I simply call

GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &G_PanelInfo_p_p);

 

The problem is that I can't seem to replicate this elsewhere, even in a test program that calls the same functions in the same order. Somehow, the callback parameter as it is stored by the labWindows call is getting corrupted, but only in that one call.

 

I'm stepping through this with the debugger, and I don't write over the parameter elsewhere, at least that I can detect.

 

I've attached the pertinent files. The whole program is huge, so I can't upload the whole thing.

In plots.c, PLOT_JPlot() starts at line 1427 with the pertinent CallCtrlCallback() at 1471.

The call ends up at the callback for the JPLOT_CURSORBUTTON control, CB_JPlotCursorToggle() at line 3430.

 

I can step through it and view the value of the pointer being passed in at line 1459, and it's not what comes out at 3443.

 

0 Kudos
Message 5 of 8
(4,623 Views)

Found the problem, and it's a puzzlement.

 

On line 1463, in PLOT_JPlot(), I make a call to    

MakeMovableCtrl(iHandle,JPLOT_GRAPH,"",0,1,0,0); - a NI call which should allow me to move the graph around.

The callback data is changed after this call.

(I simply put in GetPanelAttribute (iHandle, ATTR_CALLBACK_DATA, temp_p); statements until I noticed that it had changed).

 

Furthermore, if I set the callback data after this point the whole program crashes when it gets back to the user interface loop. Obviously, this routine uses the ATTR_CALLBACK_DATA storage in some way and doesn't like it if it's changed.

0 Kudos
Message 6 of 8
(4,614 Views)
Solution
Accepted by topic author pblase

You're probably running into this issue.

 

When dealing with custom controls, you can't set or get the callback data using ATTR_CALLBACK_DATA. This is because most custom controls use the callback chaining mechanism of the Programmer's Toolbox, and once callbacks are chained, you'll have to keep using the callback chaining API to get and set the callback data.

 

This help topic describes what you should do instead.

 

Luis

0 Kudos
Message 7 of 8
(4,585 Views)

I cut out the call to make the control movable, since I don't seem to need it anyway (darned legacy code) and it works now. Thanks

Paul

0 Kudos
Message 8 of 8
(4,560 Views)