LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling GetRawInputDeviceList function in LabVIEW

Hi,

 

I want to call GetRawInputeviceList function in the User32.dll using LabVIEW, but I am having difficulty in understandign the function prototype. To be specific, I am not clear what LabVIEW data types to be created for the arguments in the function. I went through this link http://msdn.microsoft.com/en-us/library/windows/desktop/ms645598(v=vs.85).aspx to understand the function prototype, but it is confusing.

 

Thanks

0 Kudos
Message 1 of 7
(3,387 Views)

I created a LabVIEW Example based off of the example on the MSDN. 

 

Most of the datatypes for this example boil down to unsigned ints 32-bit.  See Windows Data Types for more info.  It should also be noted that I use a hardcoded "8" for the sizeof(RAWINPUTDEVICELIST).  This is because each of the child elements are 4-byte integers.  You could check this by downloading Visual Studio and using "printf("%d\n", sizeof(RAWINPUTDEVICELIST);".

 

C++:

 

The following sample code shows a typical call to GetRawInputDeviceList:

 
UINT nDevices;
PRAWINPUTDEVICELIST pRawInputDeviceList;
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0) { Error();}
if ((pRawInputDeviceList = malloc(sizeof(RAWINPUTDEVICELIST) * nDevices)) == NULL) {Error();}
if (GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST)) == (<dtype rid="UINT"/>)-1) {Error();}
// do the job...

// after the job, free the RAWINPUTDEVICELIST
free(pRawInputDeviceList);

 

LabVIEW:

 

GetRawInputDeviceList.png

 

In case the snippet doesn't work, I also attached the VI.

 

*Note:  It should also be noted that my error checking is very minimal.  I check for the "-1" output on the first call to the function, but I really should use the Kernel32.dll to call GetLastError() as necessary.  This is obviously a simplistic example.

 

EDIT:

 

If you have any specific questions about the code or function prototyping, feel free to ask.  I'll be honest, this example took me a long while to replicate.  Getting the structure to pass correctly took some trial-and-error 😛

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If someone helped you out, please select their post as the solution and/or give them Kudos!
0 Kudos
Message 2 of 7
(3,359 Views)

Hi,

 

Thanks a lot for the VI, but I am not able to open it. I have LabVIEW version 12.0.1. Could you post the VI for version 12.0.1?

 

Thanks

 

0 Kudos
Message 3 of 7
(3,317 Views)

@Flamboyant wrote:

Hi,

 

Thanks a lot for the VI, but I am not able to open it. I have LabVIEW version 12.0.1. Could you post the VI for version 12.0.1?

 

Thanks

 


Sure thing.  Give this attachment a try.  It should be in LabVIEW 2012 format.

 

Please let me know if you have any problems or questions!

 

EDIT:

 

I actually found a bug in the program.  See my next post for an updated VI in 2012 format.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If someone helped you out, please select their post as the solution and/or give them Kudos!
0 Kudos
Message 4 of 7
(3,303 Views)

Sorry for that... The case structure was incorrect in my original example 😛

 

The output of GetRawInputDeviceList is always -1 from the first call, even when it correctly returns a value in the puiNumDevices.  As a result, you would need to use Kernel32.dll to check  GetLastError in order to determine if it worked correctly or not.

 

GetRawInputD_BD.png

 

Note:  The program may say it cannot find the path to "user32.dll".  If so, manually navigate to where you have it located.  On most installs it should be in C:\Windows\System32\User32.dll

 

Untitled.png

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If someone helped you out, please select their post as the solution and/or give them Kudos!
0 Kudos
Message 5 of 7
(3,288 Views)

A few remarks: 

 

HANDLE is a pointer sized datatype, so it is 4 bytes in a 32 bit Windows application, but 8 bytes in a 64 bit application. Because of alignment which will align the handle in each array element to its own size the array element therefore should be in LabVIEW 32 bit two uint32 but in LabVIEW 64 Bit an uint64 for the handle, then an uint32 for the dwType and another uint32 which is a filler.

 

The problem with the path to user32.dll is because  you should NOT enter the entire path in the Call Library Node configuration but only the DLL name alone. Therefore change it to "user32.dll" without any path.

 

Also use of GetLastError() is problematic in LabVIEW. Windows maintains a last error value per thread. LabVIEW is inherently multithreading. In this case the Call Library Nodes are configured to execute the call in the single threaded LabVIEW UI execution system which might seem like it will cirmumvent this problem nicely. BUT: Between the call to GetRawInputDevice() and the GetLastError() function LabVIEW is VERY likely to call quite a few other Windows API functions which might change the last error value for this thread. It is after all the UI thread which LabVIEW uses for anything user interface related and many of those functions do influence the last error value. Reliance on a correct GetLastError() value is not possible in LabVIEW if you do all the Windows API calls only through Call Library Nodes. The only way to make sure that GetLastError() returns the actual meaningful value for an API call is by creating an external shared library that packs the API call and the GetLastError() call into the same function.

Rolf Kalbermatter
My Blog
Message 6 of 7
(3,264 Views)

@rolfk wrote:

A few remarks: 

 

HANDLE is a pointer sized datatype, so it is 4 bytes in a 32 bit Windows application, but 8 bytes in a 64 bit application. Because of alignment which will align the handle in each array element to its own size the array element therefore should be in LabVIEW 32 bit two uint32 but in LabVIEW 64 Bit an uint64 for the handle, then an uint32 for the dwType and another uint32 which is a filler.

 

The problem with the path to user32.dll is because  you should NOT enter the entire path in the Call Library Node configuration but only the DLL name alone. Therefore change it to "user32.dll" without any path.

 

Also use of GetLastError() is problematic in LabVIEW. Windows maintains a last error value per thread. LabVIEW is inherently multithreading. In this case the Call Library Nodes are configured to execute the call in the single threaded LabVIEW UI execution system which might seem like it will cirmumvent this problem nicely. BUT: Between the call to GetRawInputDevice() and the GetLastError() function LabVIEW is VERY likely to call quite a few other Windows API functions which might change the last error value for this thread. It is after all the UI thread which LabVIEW uses for anything user interface related and many of those functions do influence the last error value. Reliance on a correct GetLastError() value is not possible in LabVIEW if you do all the Windows API calls only through Call Library Nodes. The only way to make sure that GetLastError() returns the actual meaningful value for an API call is by creating an external shared library that packs the API call and the GetLastError() call into the same function.


Great information, most of which I didn't know!   Quoted again for truth.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If someone helped you out, please select their post as the solution and/or give them Kudos!
0 Kudos
Message 7 of 7
(3,255 Views)