09-02-2016 07:04 PM
I am in the process of rewriting some of the production test software for the company that I am working for. The development dictates that I rewrite all of the instrument drivers placing them into a DLL. Next, I will rewrite all of the test functions placing them into another DLL. The addition to what they were doing is to add TestStand to call the test functions in the desired sequence. The old code used the old LabWindows sequencer from years ago. They insist on using the GPIB function calls rather than allow me to use the generic viWrite, viRead, etc.
I have developed the instrument drivers so that the driver keeps track of the handles. That worked find when I test the LabWindows test functions calling the instrument functions. However, I am having issues when calling the test functions through TestStand. I put MessagePopups within my instrument driver code to see what is going on. I see that the handle is there sometimes and not others. I would assume that perhaps TestStand creates different instances of the DLL code (???). Anyway, I did add a pragma to see if that would cure the issue.
struct AC_Power_Config
{
int ACPower_Device;
int ACPower_GPIB_BoardIndex;
int ACPower_GPIB_PrimaryAddress;
int ACPower_GPIB_SecondaryAddress;
int ACPower_GPIB_IOtimeout;
int ACPower_GPIB_EOImode;
int ACPower_GPIB_EOScharacter;
};
//
#if defined(__AC_POWER_SUPPLY__)
#pragma data_seg("AC_POWER_SHARED")
//
int ACPower_GPIB_Handle = -1;
struct AC_Power_Config AC_Power_Configuration;
//
#pragma data_seg()
#pragma comment(linker, "/section:AC_POWER_SHARED,RWS")
#endif
It did not. I am not sure if I passed the handle back to TestStand allowing it to keep track of the handles, if the handles would still work.
Are there some instructions that I can put into my LabWindows code or some link options that I can use to make sure that the handles are kept in the DLL memory area and that all function calls reference this memory? Any thoughts on the best method to handle this would be appreciated. Although changing the overall design (TestStand to DLL to DLL) cannot be done.
Thank you
Solved! Go to Solution.
09-06-2016 10:03 PM
Hi Bill,
I'm sorry to hear you're running into that, it seems like pretty strange behavior. Just to clarify, when you say "I see that the handle is there sometimes and not others" do you mean the behavior varies betwen different runs of the sequence or in one run, some handles are there but others aren't?
Also, how are you calling the DLL? I'm not sure if you've seen this already or not but this KB may be helpful in making sure there aren't multiple instances of the DLL in memory at one time:
"Multiple Instances of DLLs or Sequence Files in Memory Are Possible with TestStand"
http://digital.ni.com/public.nsf/allkb/6E1FF9F8EB5DCC0086256944004B90B0
09-07-2016 02:41 PM - edited 09-07-2016 02:44 PM
Genius !!!
I wish that I could give you millions of Kudos.
Thank you for your help your majesty.
I checked the link that you provided against my TestStand code. That was not my problem.
However, it helped me realize my problem.
My TestStand code would call my LabWindows test functions which were located in, shall we say, TestFunctions.dll . The functions located within TestFunctions.dll would call the instrument driver functions located in, shall we say, InstrumentDrivers.dll. This created the first instance to the instrument driver functions.
I decided to place all of my instrument initialization functions (open a link to the device to get a handle and perform an “IDN?” command to verify that the code is talking to the correct instrument) into the TestStand MainSequence Setup. I placed the instrument close functions (reset the device to a known state and release the handle) into the MainSequence Cleanup. To make life easier (I thought), I called those instrument driver functions directly from InstrumentDrivers.dll . This created a second instance to the instrument driver functions. While this second instance maintained the handle, since those were the functions that initialized the instruments, the first instance did not have those handles defined. Thus, the calls to the test functions did not work.
My solution was to create wrapper functions within TestFunctions.dll and perform all of my instrument driver calls through TestFunctions.dll. (not directly through InstrumentDrivers.dll)
Examples:
ViStatus __declspec(dllexport) INSTR_ACPower_Close (void)
{
return ACPower_Close ();
}
ViStatus __declspec(dllexport) INSTR_ACPower_GetOutputCurrent (double *OutputCurrent)
{
return ACPower_GetOutputCurrent (OutputCurrent);
}
ViStatus __declspec(dllexport) INSTR_ACPower_GetOutputVoltage (double *OutputVoltage)
{
return ACPower_GetOutputVoltage (OutputVoltage);
}
ViStatus __declspec(dllexport) INSTR_ACPower_Initialize (void)
{
return ACPower_Initialize ();
}
ViStatus __declspec(dllexport) INSTR_ACPower_Reset (void)
{
return ACPower_Reset ();
}
ViStatus __declspec(dllexport) INSTR_ACPower_SetSupply (float Voltage, float Current, int ON_or_OFF, int DelaySeconds)
{
return ACPower_SetSupply (Voltage, Current, ON_or_OFF, DelaySeconds);
}
ViStatus __declspec(dllexport) INSTR_ACPower_Turn (int ON_or_OFF)
{
return ACPower_Turn (ON_or_OFF);
}
09-07-2016 06:17 PM
Hi Bill,
Awesome!!! I'm so very happy to hear you figured that out! Also thanks for posting such detailed responses, I know that will be really helpful to anyone else who runs in to a similar problem. Have a great day 🙂
09-13-2016 03:37 PM
With a little further research and testing I determined the issue and resolved it.
Due to this company’s policies on computer security, I need to work out of my personal folders. My lead has not decided exactly where the final software will be installed (which folders on the system drive). As such, I have placed all of the instrument drivers under a folder named InstrumentDrivers. The instrument driver DLL is built within this folder and resides within this folder. The test code, TestFunctions.dll, and TestStand sequence files are located within a folder named TestFunctions at the same level as the InstrumentDrivers folder. When I compile the test function code, I have, within the project, a link to the InstrumentDriver.lib file located within the InstrumentDrivers folder. When I ran the LabWindows test function code, LabWindows gave me an error that it could not find InstrumentDrivers.dll. I copied InstrumentDrivers.dll into the TestFunctions folder so that I could verify the test functions prior to executing them through TestStand. After confirming that the code worked, I created the TestStand sequence to run the test code. For the initialize and close functions that I link to the InstrumentDrivers.dll, I pointed to the version within the TestFunctions folder rather than the InstrumentDrivers folder. Once I changed the location of the InstrumentDriver.dll file, within TestStand, it worked without the wrapper code.
I know there are ways within LabWindows and TestStand to add search paths. I was not doing that because my personal folder will not be the final location of the files. I was hoping to not confuse myself later when the code is moved to its final resting place.