Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

Run-Time Dynamic Linking to Visa32

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 computer 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); }
0 Kudos
Message 1 of 3
(4,855 Views)

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);
    }


0 Kudos
Message 2 of 3
(4,850 Views)

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

 

 

0 Kudos
Message 3 of 3
(4,831 Views)