08-29-2006 11:32 AM
WinMain program calls a DLLMain program which dynamically loads (LoadExxternalModule) a subsidiary DLL that calls the hp662xa IVI driver.
This configuration works in some scenarios and results in a GPF at the IVI driver function call in others.
From WinMain I call a PS_Config function in DLLMain that configures the power supply. I then call functions PS_Enable and PS_Disable in DLLMain (from WinMain).
At this point everything appears to be functioning correctly.
Scenario 1:
After the above DLL function calls I call DisplayPanel (pH). The panel contains a Quit Button and a toggle button that calls the PS_Enable & PS_Disable DLL functions. When I select the toggle button I get the GPF.
Scenario 2:
I tried calling DisplayPanel (pH) before configuring the power supply and again received a GPF when I clicked the panel toggle button.
Scenario 3:
I inserted a MessagePopup( ) in the PS_Config function in DLLMain. When I repeat scenario 1 I still get the GPF. However, when I repeat scenario 2 with the MessagePopup the program functions properly.
I read in the NI literature that you can get a GPF if the calling conventions are not correct. How can calling a DLL function from WinMain work while the toggle button CALLBACK function in main (which calls the same DLL function) produce a GPF? And then not produce a GPF when a MessagPopup is called from DLLMain?
08-30-2006 06:17 PM
08-31-2006 02:35 PM
Terry,
The Default Calling Convention for WinMAin, DLLMain, & the SubDLL was set to __cdecl. I found that the hp662xa driver uses _VI_FUNC ( which for CVI is __stdcall). I changed all three projects Default Calling Convention to __stdcall. Again, from WinMain I call a PS_Config function in DLLMain that configures the power supply (hp662xa_DeviceInit, hp662xa_ConfigureVoltageLevel,…). This calls, plus PS_Enable & PS_Disable, work before or after the DisplayPanel (pH) call.
When I call PS_Enable or PS_Disable from the Toggle Control Callback, I get a GPF error in the SubDLL where I call the driver (below).
int ps6624_OutputEnable ( ViSession ps_handle, ViInt32 channel, ViInt32 value )
{
ViStatus Status = VI_SUCCESS;
ViChar _VI_FAR chanStr[128];
sprintf (chanStr, "%d", channel);
if ( Status = hp662xa_ConfigureOutputEnabled (ps_handle, chanStr, VI_TRUE) ) goto Error;
Error:
if (Status) {
}
return Status;
}
When I call PS_Config, then DisplayPanel, followed by PS_Enable or PS_Disable I get the GPF in the same location.
I tried placing __stdcall in the DLLMaion and SubDLL but still get the GPF.
int __stdcall PS_Config( void )
int __stdcall ps6624_OutputEnable ( ViSession ps_handle, ViInt32 channel, ViInt32 value )
The above is true whether I use the MessagePopup or not. It looks like a calling convention or scope issue. Any suggestions would be greatly appreciated.
Thanks,
Jim
09-01-2006 02:34 PM
09-02-2006 02:06 PM
I added the hp662xa.lib & .h to WinMain and called the DeviceInit & queried the instrument model from WinMain with no problem. I also tried adding the hp662xa.lib to the DLLMain & WinMain projects (one at a time) and use the LoadExternalModule SubDLL and the program ran fine in each case.
When I add the SubDLL project to the same .cws that contains the Main & DLLMain projects the program again functions properly.
From WinMain I call DisplayPanel, then call a function in the DLLmain that configures the power supply. From WinMain I can call the Configure_NomVolt (PTR) function in DLLMain. This Configure_NomVolt(PTR) function calls the Command_SetNomVolt (PTR, chan) function also in DLLMain. This function performs the LoadExternalModule.
int Command_SetNomVolt ( PowerDisplayStruct *TP, int chan ) {
int Status = 0;
sprintf (ps_cmd, "ps%d_VoltageLevel", TP->ModelNo[chan]); // 6624
xm_handle = LoadExternalModule (TP->DLL_Library[chan]); // This is my ps6624_dll.lib file
cmdptr = GetExternalModuleAddr (xm_handle, ps_cmd, &Status);
Status = (*cmdptr)(TP->PS_Handle[chan], TP->ChannelOut[chan], TP->NomVolt[chan]);
UnloadExternalModule (xm_handle);
return Status;
}
This is the SubDLL (ps6624_dll.lib) call to the hp662xa driver:
int ps6624_VoltageLevel ( ViSession ps_handle, ViInt32 channel, ViReal64 value ) {
ViStatus Status = VI_SUCCESS;
ViChar _VI_FAR chanStr[32];
sprintf (chanStr, "%d", channel);
if ( Status = hp662xa_ConfigureVoltageLevel (ps_handle, chanStr, value) ) goto Error;
Error:
return Status;
}
This works fine when called from WinMain. When I call Configure_NomVolt(PTR) from the Toggle Control Callback (which is also in WinMain) I get the GPF at hp662xa_ConfigureVoltageLevel (ps_handle, chanStr, value). Why does it work when called from WinMain and not the Toggle Control Callback (EVENT_COMMIT) in WinMain?
Note: I have Embed Project .UIR’s selected in Target Settings.
Thanks,
Jim
09-05-2006 04:33 PM
09-07-2006 09:18 AM
Attached is the DLLMain with the pertinent DLL functions included. Please let me know if you need any more info (or if the attachment doesn't come through).
Thanks,
Jim
09-08-2006 03:11 PM
09-11-2006 12:14 PM
09-12-2006 04:07 PM
Jim,
Terry is out of the office this week, so I'll continue to help in his absence.
I ran the code that you sent me, and after installing the IVI driver, it ran correctly, with no General Protection Fault. I'm not sure what I'm doing differently, but I'm attaching the code that I was using, to make sure that we have identical versions.
If you're still experiencing this trouble, if you could pare down the code a little, and send me just the bare minimum to reproduce the fault, I'll be happy to troubleshoot it further.
Josh W | National Instruments | Applications Engineer