Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

Access ni4882.dll with Qt and MinGW

Solved!
Go to solution

I have to control some electric loads and power supplies over GPIB. We use Qt 4.7.4 with MinGW 4.4 (32-bit) on Windows 7 64-bit.

 

The packet NI-488.2 GPIB Drivers packet 3.0.2 for Windows 7 64-bit is installed. The GPIB Troubleshooting Utility tool shows "pass" and the Measurement & Automation application can connect to the board and talk to an intrument. So far so good.

 

Now I want to write an application to use the NI4882.dll (3.0.0.49153). Unfortunately, there are just object files for Microsoft and Borland compilers and no lib file.

 

So we generate a def file from the ni4882.dll with:

pexports -h ni4882.h ni4882.dll > ni4882.def

 

-ni4882.def-

LIBRARY NI4882.dll
EXPORTS
?compareVersion@nGPIBAPI_NI4882@@YGXABVtSSVersion@@0AAJPBD@Z
?getCurrentVersion@nGPIBAPI_NI4882@@YG?AVtSSVersion@@AAJ@Z
?getOldestCompatibleVersion@nGPIBAPI_NI4882@@YG?AVtSSVersion@@AAJ@Z
AllSpoll@12
DevClear@8
DevClearList@8
...

--

 

Then generate the lib with:

 

dlltool -k -D ni4882.dll -d ni4882.def -l libni4882.a

 

Now, I've build a small test program in Qt.


-.pro file-

INCLUDEPATH += $$PWD/include

LIBS += $$PWD/lib/libni4882.a

--

 

-.cpp file-

#include "ni4882.h"

...

 

void MainWindow::Init()

{

  int dd = idev(0,3,0,T10s,1,0);

  if(Ibsta()&ERR)

  {

    Err(tr("Unable to open board:ibdev=%1").arg(dd));

  }

 

  if( ibonl(0,0)&ERR)

  {

    Err(tr("Unable to close board"));

  }

}

 

void MainWindow::Err(QString message)

{

  switch(Iberr())

  {

    case 0:

    {

      message.append("(EDVR - System error)");

    } break;

    ...

  }

 

  qDebug("Error : %s\nibsta = 0x%x iberr = %d\n",

    (unsigned int)Ibsta(), (int)Iberr());

}

--


The source code will be compiled and linked without an error.

 

But if I run it, the output is:

Error : Unable to open board: ibdev=32768 (EDVR - System error)

ibsta = 0x8000 iberr = 0

 

Error : Unable to close board (EDVR - System error)

ibsta = 0x8000 iberr = 0

 

So, the question is: What is wrong? Why do I always receive this EDVR error. I also tried SendIFC(0) with the same result.

 

With the GPIB Interactive Control tool, I can communicate with my instrument and the NI I/O Trace logs it. But I can't see logs in the Trace tool from my application. Is this an indication?

 

Any ideas?

Marko

Message 1 of 19
(11,901 Views)

Hi Marko,

 

Currently NI4882.dll only works when using our provided object file.  This will prevent you from using NI4882.dll with Qt.  That limitation will be removed in the next release.  

 

Are you making a 32 bit application?  If so you can use the gpib-32.dll which does not have the same limitation.

 

Please let me know if you have any questions.

Justin Parker
National Instruments
Product Support Engineer
0 Kudos
Message 2 of 19
(11,865 Views)

Hi Justin,

 

thank you for your answer.

 

I don't understand why it's necessary to use you *.obj file instead of creating a *.a file as described above? What is the difference?

 

So I try to use the GPIB-32.dll.

 

Regards

Marko

0 Kudos
Message 3 of 19
(11,857 Views)

Hi Marko,

 

It shouldn't be necessary to use our object file.  This is something we are addressing in the next release.  Hopefully gpib-32.dll will work for you.

Justin Parker
National Instruments
Product Support Engineer
0 Kudos
Message 4 of 19
(11,848 Views)
Solution
Accepted by topic author MarkoSat

Hi to all,

 

after some questions about using the GPIB library with Qt, I've written a step by step description to create object files for MinGW:

 

1. Create a folder and copy the "gpib-32.dll" from the "C:\Windows\System32" ("C:\Windows\SysWOW64" in Win7) to this folder.

2. Copy "ni488.h" from "c:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include\". (Not ni4882.h!)

3. Load PExports (my version is 0.44) and put the exe in your folder to. I do not have a URL to load this tool but should be easy to find. It's freeware.

4. Copy dlltool.exe from "c:\QtSDK\mingw\bin\" to your folder.

5. Create a batch file "1 - build def file.bat" with the content: "pexports -h ni488.h gpib-32.dll > gpib.def"

6. Create a batch file "2 - build lib file.bat" with the content: "dlltool -k -D gpib-32.dll -d gpib.def -l libgpib.a"

7. Start the batch file "1 - build def file.bat" to create the def file "gpib.def"

8. Start the batch file "2 - build lib file.bat" to create the library file "libgpib.a"

9. Copy "gpib-32.dll" and "libgpib.a" to your software project. I created the subfolder "lib" and copied the files into.

10. Copy "ni488.h" to your software project. I created the subfolder "include" and copied the file into.

11. Into your PRO file type:

 

# #####################################################################
# Include the NI 488.2 library
# #####################################################################
INCLUDEPATH += $$PWD/include
HEADERS += include/ni488.h

LIBS += $$PWD/lib/libgpib.a

 

12. In your source code type:

#include "windows.h"
#include "ni488.h"

 

bool InitializeGPIBBoard( )

{

bool isStarting = false;

int boardID;        /** @brief Board id. */
QString boardName;  /** @brief Board name. */
int boardDescr;     /** @brief Board descriptor. */

// Get board ID
SendIFC(boardID);

if( ThreadIbsta() & ERR )
{
    ErrorHandling(tr("Unable to open board"));

    return isStarting;
}

// Open and initialize a board or a user-configured device descriptor
wchar_t *aName = new wchar_t[boardName.size()+1];
m_para.boardName.toWCharArray( aName );
aName[boardName.size()] = 0;
m_para.boardDescr = ibfind( aName );
delete []aName;

// The board is the System Controller.
if( ibconfig( boardDescr, IbcSC, 1 ) & ERR )
{
    ErrorHandling(tr("Unable to set the board to System Controller"));

    return isStarting;
}

// Assert interface clear.
if( ibsic( boardDescr ) & ERR )
{
    ErrorHandling(tr("Assert interface clear"));

    return isStarting;
}

// aso.

isStarted = true;

 

return isStarted;

}

13. Be happy! 🙂

 

I hope that helps. If you have problems, please write me a message or post on this board thread.

 

Gruß und viel Erfolg!
Marko

Message 5 of 19
(11,592 Views)

Thanks for posting to share your experience with others. As of NI-488.2 3.1 you should be able to access ni4882.dll without the use of the NI object file as well. This opens up the possibility of using it with 64-bit applications.

 

NI-488.2 3.1

 

-Jason Smith

0 Kudos
Message 6 of 19
(11,580 Views)

Jason, thanks for your remark.

 

I use NI-488.2 3.0.2. Cause of project restrictions it is not possible to use a newer version. Smiley Sad

 

So guys, use the newest library version if possible. Smiley Happy

 

Bye

Marko

0 Kudos
Message 7 of 19
(11,577 Views)

Hi Marko,

 

i can´t create the libgpib.a Smiley Sad

can you send me the file?

thanks

0 Kudos
Message 8 of 19
(11,569 Views)

OK, I sure kuoyaoming managed it throw,

But if there is anyone that get the same problem...

 

I failed to create the .a file too, and get workaround by loading the gpib-32.dll dynamically.

 

Some code:

gpib.h:

#include <windows.h>

typedef int _stdcall (*ibdevPtr)        (int boardID, int pad, int sad, int tmo, int eot, int eos);
typedef int _stdcall (*ibwrtPtr)        (int ud, PVOID buf, long cnt);
typedef int _stdcall (*ibrdPtr)         (int ud, PVOID buf, long cnt);

class GPIB482
{
public:
    GPIB482();

private:
    int loadDllDynamically();

    HINSTANCE       hLib;
    ibdevPtr        ibdev;
    ibwrtPtr        ibwrt;
    ibrdPtr         ibrd;
};

#endif // GPIB482_H

 gpib.cpp

GPIB482::GPIB482()
{
    loadDllDynamically();

    //Now, for the [dummy] example:
    int dev = (ibdev)(0, 1, 0, 11, 1, 0);
    (ibwrt)(dev, "GOOD", 4);
}

int GPIB482::loadDllDynamically()
{
    local_dll_adr = "C:/Windows/System32/gpib.dll";
    hLib = LoadLibraryA(local_dll_adr.toStdString().c_str());
    if (hLib == NULL) {
        QMessageBox::warning(0,"","Failed load lib");
        return -ENOSYS;
    }
    ibdev = (ibdevPtr) GetProcAddress(hLib, "ibdev");
    if (ibdev == NULL) {
        QMessageBox::warning(0,"","Failed find ibdev");
        return -ENOSYS;
    }
    ibwrt = (ibwrtPtr) GetProcAddress(hLib, "ibwrt");
    if (ibwrt == NULL) {
        QMessageBox::warning(0,"","Failed find ibwrt");
        return -ENOSYS;
    }
    ibrd = (ibrdPtr) GetProcAddress(hLib, "ibrd");
    if (ibrd == NULL) {
        QMessageBox::warning(0,"","Failed find ibrd");
        return -ENOSYS;
    }    
    return SUCCESS;
}

That's all,

Hope i been helping for someone...

 

Aviad

0 Kudos
Message 9 of 19
(10,437 Views)

Anyone using MarkoSat's method -- make sure to include "windows.h" before "ni488.h".  This appears to be working with the new version of pexports (0.46).

0 Kudos
Message 10 of 19
(10,131 Views)