LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

An imported USB api won't work properly

Solved!
Go to solution

Good morning everyone,

 

I am currently trying to use LabVIEW to communicate with a USB device and for that I had to import a USB api I bought. Together with VC++ this api is working fine, but LabVIEW has its issues.

First of all, I imported it through Tools>Import>Library(DLL), selected the DLL and the corresponding Headerfile and all that worked without problems. Now I got my 14 VI's, one for each function declared in the DLL.

 

Problem is, most of these functions won't work properly, or maybe I just don't understand them right or give them the wrong parameters. I'll attach a screenshot of the "GetList.vi" which should retrieve a list of all connected USB devices.

 

My guess is that the defined pList might be a problem for it should contain char, int etc. but, as you can see in the screenshot, only contains numbers.

 

Any help would be greatly appreciated!

 

Regards,

 

Pedro

 

EDIT: here is the description of the GetList method from the USB api documentation:

 

GetList( )
This function searches the system for attached USB HID devices and builds a list of these devices and their availability.  The caller must supply a pointer to a buffer that will hold the list of structure entries.  Must also supply an integer representing maximum no. of entries the buffer can hold.  Returns total number stored.

int CUsbHidApi::GetList(
   unsigned int VendorID,
   unsigned int ProductID,
   char         *Manufacturer,
   char         *SerialNum,
   char         *DeviceName,
   mdeviceList  *pList,
   int          nMaxDevices);

Parameter descriptions:

   VendorID     // Vendor ID to search  (0xffff if unused)
   ProductID    // Product ID to search (0xffff if unused)
   Manufacturer // Manufacturer            (NULL if unused)
   SerialNum    // Serial number to search (NULL if unused)
   DeviceName   // Device name to search   (NULL if unused)
   pList        // Caller's array for storing device(s)
   nMaxDevices  // Size of the caller's array list (no.entries)

0 Kudos
Message 1 of 8
(3,282 Views)

Showing us the front panel tells us nothing. You have to show how the CLFN was configured, and what datatypes were created. Your function uses pointer to an "mDeviceList". What is this datatype?

 

You should also be aware that the CLFN is only compatible with C DLLs, not C++ DLLs. It can use C++ DLLs, as long as the functions have had the "extern 'C'" as part of the function definition to prevent the functions names from being "decorated". There is also the restriction that you can't call classes (again, because it's only designed to work with C DLLs, not C++ DLLs). In your particular case that's what you're trying to do. Thus, you'd need to write a wrapper C DLL in order to use that API.

0 Kudos
Message 2 of 8
(3,263 Views)

 

Thanks for the reply,

 

I'll attach some detailed info in the DLL, but what I can certainly say is: it's a ANSI C DLL, not C++.

The problem is probably the mDeviceList, a struct defined in the DLL header and as I've read all over the internet, LabView has its problem with these. Anyhow, here is the Headerfile and the VI for the DLL.

If you need anything more to help, please tell me 😉

 

Regards,

 

Pedro

 

 

Download All
0 Kudos
Message 3 of 8
(3,260 Views)

@Pedro89 wrote:

Thanks for the reply,

 

I'll attach some detailed info in the DLL, but what I can certainly say is: it's a ANSI C DLL, not C++.

 


int CUsbHidApi::GetList  is not ANSI C. It's C++.

0 Kudos
Message 4 of 8
(3,257 Views)

But it says in the header file:

 

#ifdef __cplusplus
   extern "C" {
#endif
__declspec(dllexport) int _stdcall GetList(unsigned int VendorID,      // Vendor ID to search  (0xffff if unused)
                                     unsigned int ProductID,	   // Product ID to search (0xffff if unused)
                                     char         *Manufacturer, // Manufacturer            (NULL if unused)
                                     char         *SerialNum,    // Serial number to search (NULL if unused)
                                     char         *DeviceName,   // Device name to search   (NULL if unused)
                                     mdeviceList2 *pList,        // Caller's array for storing matching device(s)             
                                     int          nMaxDevices);  // Size of the caller's array list (no.entries)
#ifdef __cplusplus
}
#endif

 so shouldn't it work?

0 Kudos
Message 5 of 8
(3,249 Views)

When I posted by response you still had not posted any header file, thus I did not see the header which you posted 2 minutes after my reply. Given the header, you should be able to call those functions. However, the pList parameter is a pointer to a struct, which contains variable length strings. This is not something that you can easily handle, and this sort of issue has been discussed several times on this forum. When you get to that level of complexity in terms of parameter datatypes you have to write a wrapper DLL so that the datatypes between LabVIEW and the DLL are simple datatypes only.

0 Kudos
Message 6 of 8
(3,237 Views)
Solution
Accepted by topic author Pedro89

@smercurio_fc wrote:

When I posted by response you still had not posted any header file, thus I did not see the header which you posted 2 minutes after my reply. Given the header, you should be able to call those functions. However, the pList parameter is a pointer to a struct, which contains variable length strings. This is not something that you can easily handle, and this sort of issue has been discussed several times on this forum. When you get to that level of complexity in terms of parameter datatypes you have to write a wrapper DLL so that the datatypes between LabVIEW and the DLL are simple datatypes only.



Actually the code created byt the import library wizard does handle those variable sized pointers correctly for one element in the structure, so nMaxDevices should never be set to anything else but 1.

 

It's not fully clear either if Manufacturer, DeviceName and SerialNum are always inputs to the function or not, but I assume they are. One problem here is that the DLL function expects a NULL pointer if it should ignore the according string parameter and not just an empty string, so you will probably have to create multiple Call Library Nodes with different parameter configuration in order to allow ignoring one or more of those parameters.

 

The mDeviceList datatype as originally used by the library with fixed size embedded strings would have been a bit more efficient to implement in LabVIEW but still a pita too.

 

I can only acknowledge smercurios statement that this type of API is absolutely best handled with a wrapper DLL. While it's not impossible to do entirely in LabVIEW it's more than the import library wizard can possibly handle automatically and therefore requires some advanced memory pointer acrobatics in the LabVIEW diagram that need to be done manually. Something that is not really handled by someone without some serious C programming knowledge but such a person clearly goes for the wrapper DLL solution since it is much more maintainable than doing it all in a LabVIEW diagram by hand.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 7 of 8
(3,227 Views)

Hi everybody,

 

Thanks for all your support regarding my problem. Seems like I won't get around creating a wrapper DLL. Let's see, if I'm able to do that Smiley Tongue

 

Have a great day,

 

Regards,

 

Pedro

0 Kudos
Message 8 of 8
(3,209 Views)