09-06-2012 08:21 AM
09-06-2012 08:38 AM
Replying to my own message to improve the formatting!!!
Hi,
I am trying to use a Tektronix oscilloscope over USB with NI-VISA 5.1.1.
My 32bit application is written in the Qt framework using C++ and the mingw compiler (standard Qt 4.7 SDK).
My app has no problems communicating with the device when I statically link to visa32.lib. My dynamically linked code also runs fine on a Win7 platform, but crashes on two different computers running on WinXP sp3 (32bit).
I have traced the line of code that causes the crash (the stack seems to get corrupted since in the debugger it jumps out of the subroutine then seg faults).
I don't understand what is going wrong...but I know the first call to pviWrite is the culprit. So I am posting my code here hoping someone can see the error that I can't.
Note I made sure to install the exact same version of NI-VISA on all 3 machines. I also checked the address stored in the function pointers by the GetProcAddress call, they match exactly in all cases.
Thanks for any help on this,
Eric
The declarations for the function prototypes in the header file:
typedef long (*tviOpenDefaultRM)(ViPSession);
typedef long (*tviOpen)(ViSession, ViRsrc, ViAccessMode, ViUInt32, ViPSession);
typedef long (*tviClose)(ViObject);
typedef long (*tviRead)(ViSession, ViPBuf, ViUInt32, ViPUInt32);
typedef long (*tviWrite)(ViSession, ViBuf, ViUInt32, ViPUInt32);
typedef long (*tviFindRsrc)(ViSession, ViString, ViPFindList, ViPUInt32, ViChar*);
typedef long (*tviFindNext)(ViSession, ViChar*);
tviOpenDefaultRM pviOpenDefaultRM;
tviOpen pviOpen;
tviClose pviClose;
tviRead pviRead;
tviWrite pviWrite;
tviFindRsrc pviFindRsrc;
tviFindNext pviFindNext;
The executing part of the app:
QLibrary visa32("visa32"); // Qt wrapper for LoadLibrary
if (!visa32.load()) throw "Unable to load visa32.dll";
pviOpenDefaultRM = (tviOpenDefaultRM) visa32.resolve("viOpenDefaultRM"); //Qt wrapper for GetProcAddress
if (pviOpenDefaultRM == 0) throw "Unable to resolve function viOpenDefaultRM in visa32.dll";
pviOpen = (tviOpen) visa32.resolve("viOpen");
if (pviOpen == 0) throw "Unable to resolve function viOpen in visa32.dll";
pviClose = (tviClose) visa32.resolve("viClose");
if (pviClose == 0) throw "Unable to resolve function viClose in visa32.dll";
pviRead = (tviRead) visa32.resolve("viRead");
if (pviRead == 0) throw "Unable to resolve function viRead in visa32.dll";
pviWrite = (tviWrite) visa32.resolve("viWrite");
if (pviWrite == 0) throw "Unable to resolve function viWrite in visa32.dll";
pviFindRsrc=(tviFindRsrc) visa32.resolve("viFindRsrc");
if (pviFindRsrc== 0) throw "Unable to resolve function viFindRsrc in visa32.dll";
pviFindNext = (tviFindNext) visa32.resolve("viFindNext");
if (pviFindNext == 0) throw "Unable to resolve function viFindNext in visa32.dll";
ViSession rm;
ViStatus status = pviOpenDefaultRM(&rm);
if (status < VI_SUCCESS) return false;
ViFindList list;
ViUInt32 itemCnt = 0;
char desc[VI_FIND_BUFLEN];
const int BUFFERSIZE = 256;
char query[BUFFERSIZE];
char idn[BUFFERSIZE];
char id[BUFFERSIZE];
memset(query, 0, sizeof(query));
memset(idn, 0, sizeof(idn));
memset(id, 0, sizeof(id));
strcpy((char*) idn, "*idn?");
strcpy((char*) query, "USB?*");
// Find all USB devices
status = pviFindRsrc(rm, query, &list, &itemCnt, desc);
if (status < VI_SUCCESS) return false;
for (int i = 0; i < (int) itemCnt; ++i) {
// Open resource found in rsrc list
ViSession vi = VI_NULL;
status = pviOpen(rm, desc, VI_EXCLUSIVE_LOCK, VI_NULL, &vi);
if (status < VI_SUCCESS) return false;
// Send an ID query.
ViUInt32 retCnt = 0;
status = pviWrite(vi, (ViByte*) idn, 5, &retCnt); // crash right here
if (status < VI_SUCCESS) return false;
// Clear the buffer and read the response
memset(id, 0, sizeof(id));
status = pviRead(vi, (ViByte*) id, sizeof(id), &retCnt);
if (status < VI_SUCCESS) return false;
// We're done with this device so close it
pviClose(vi);
QString idstring((const char*) id);
if (idstring.indexOf("TEKTRONIX,TDS") == 0) {
status = pviOpen(rm, desc, VI_EXCLUSIVE_LOCK, VI_NULL, &mviDevice);
if (status >= VI_SUCCESS) return true;
}
// Get the next item
pviFindNext(list, desc);
}
09-09-2012 06:33 PM
Some more information about my problem:
The issue seems to be related to setup of global variables in the DLL itself. If I call the following (where the vi prefixed function are statically linked and pvi ones are runtime linked)
status = viOpenDefaultRM(&rm);
status = viFindRsrc(rm, query, &list, &itemCnt, desc);
status = viOpen(rm, desc, VI_NULL, VI_NULL, &vi);
status = pviWrite(vi, (ViByte*) idn, 5, &retCnt); // crash right here
status = pviRead(vi, (ViByte*) id, sizeof(id), &retCnt);
everything works perfectly. However changing any of the three setup function to runtime linked causes a seg fault when calling pviWrite. Is there another function that must be called to properly setup the DLL? Is runtime linking even possible? I can't find any examples on the net.
Thanks for any pointers,
Eric