LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Calling functions from a DLL without header and libraryfiles

Hello all,
 
I have a file, usbdll.dll (see attachment), located in system32 directory, which I would like to use in my application. Problem is: I do not have a header file, nor any library file. When I try to load the file with the ActiveX control wizard, I get a Win32 error.
 
However, with LabVIEW, I can call functions from this dll, using the "Call Library Function" block. When I select the usbdll.dll file in the "Library name or path" field, I can see the three functions in the "Function name" dropdown menu. How can I call this functions using CVI instead of LabVIEW?
 
thx for all replies,
Wim
0 Kudos
Message 1 of 5
(15,472 Views)
Hi Wim S,

Have you been able to actually call the DLL from LabVIEW successfully? My guess would be no unless you know what parameters those 3 functions take. That DLL has exported 3 functions for use and the "Call Library Function Node" is simply populating the drop-down list with whatever functions if finds that are exported. However, it is up to the user to indicate what parameters those functions take. Typically you have some sort of documenation or header file that indicates this.

Other tools like Dependency Walker and dumpbin.exe (Microsoft tool that allows you to dump the DLL exports to a file) also only show the function names and nothing else.

Once you find out what parameters those functions take, you can use LoadLibrary and GetProcAddress to call those DLL functions dynamically (see the
How Can I Access DLL Functions in a LabWindows/CVI Program Without Including the Import Library in t... KnowledgeBase). Or if you can find the import library (.lib) and the header file (.h), you can also link to the DLL statically.

Either approach requires you to have some knowledge of what parameters those functions take. If you know that, then you are good to go.

Best Regards,
Jonathan N.
National Instruments
Message 2 of 5
(15,457 Views)

Hello Jonathan,

thanks a lot for your response. With the driver for my device, I got a LabVIEW example. Thanks to this example I know what parameters should be passed to the dll functions. Thanks to your post, I now know how to call these functions, however When executing the "Write" function, I got the error "CVI has detected an inconsistancy of the run-time stack. This might have been caused by calling convention mismatch in the last function call." This is on the line " error = (UsbdllWrite) (4, "*IDN?\r\n", 7);" of the code below. Note that the GetProcAddress functions all result in valid addresses. And that the execution of the UsbdllInit function is successful.

Any idea what is causing the error?

--------------------------------------------------------

#include <windows.h>
#include <userint.h>

typedef long (__cdecl *INITPROC)(void);
typedef long (__cdecl *WRITEPROC)(long nDeviceID, unsigned char *strCommand, long command_length);
typedef long (__cdecl *READPROC)(long nDeviceID, unsigned char *strResponse, long buffer_size, long *response_length);

INITPROC UsbdllInit;
WRITEPROC UsbdllWrite;
READPROC UsbdllRead;

HINSTANCE hinstUsbdll;

int main (int argc, char *argv[]) {
 long error;
 char pathname [MAX_PATHNAME_LEN];
 unsigned char response[256];
 long response_length;
 
 // Initialize the CVI Run Time Engine.
 if (InitCVIRTE (0, argv, 0) == 0)
  return -1; /* out of memory */
 
 hinstUsbdll = 0;
 
 // Get windows system directory.
 if (GetSystemDirectory (pathname, MAX_PATHNAME_LEN) == FALSE)
  strcpy (pathname, "C:\\WINOWS\\system32");
 
 // Create path of the dll.
 strcat (pathname, "\\usbdll.dll");

 // Load the library module.
    hinstUsbdll = LoadLibrary (TEXT(pathname));
 
 // Display error message if loading the module failed.
 if (!hinstUsbdll){
  MessagePopup ("Error", "Loading usbdll.dll failed!");
  return 0;
 }
 
 // Get usbdll.dll function addresses.
 UsbdllInit = (INITPROC) GetProcAddress(hinstUsbdll, "newp_usb_init_system");
 UsbdllWrite = (WRITEPROC) GetProcAddress(hinstUsbdll, "newp_usb_send_ascii");
 UsbdllRead = (READPROC) GetProcAddress(hinstUsbdll, "newp_usb_get_ascii");
 
 // Execute newp_usb_init_system function.
 error = (UsbdllInit) ();
 if (error){
  MessagePopup ("Error", "Error while initializing.");
  goto Error;
 }
 
 // Execute newp_usb_send_ascii function.
 error = (UsbdllWrite) (4, "*IDN?\r\n", 7);
 if (error){
  MessagePopup ("Error", "Error while writing.");
  goto Error;
 }
 
 // Execute newp_usb_get_ascii function.
 error = (UsbdllRead) (4, response, 256, &response_length);
 if (error){
  MessagePopup ("Error", "Error while writing.");
  goto Error;
 }
 
 // Free Library if it was loaded successfully.
Error:
 if (hinstUsbdll) FreeLibrary (hinstUsbdll);
 
 return 0;
}
--------------------------------------------------------

If you need some more information, please let me know...

0 Kudos
Message 3 of 5
(15,415 Views)

Where did you get the information:

    typedef long (__cdecl *INITPROC)(void);
    typedef long (__cdecl *WRITEPROC)(long nDeviceID, unsigned char *strCommand, long command_length);
    typedef long (__cdecl *READPROC)(long nDeviceID, unsigned char *strResponse, long buffer_size, long *response_length);

from? It is normal practice to use __stdcall for general-purpose dll functions. Note that it IS possible for the wrong calling convention to appear to work - it all depends on how many parameters are passed and what other stack usage is made after the incorrect call is made.

Try the functions using __stdcall instead of __cdecl.

JR

Message 4 of 5
(15,411 Views)

Hello JR,

I got it from this example code when searching for the LoadLibrary function : http://msdn2.microsoft.com/en-us/library/ms686944.aspx

Anyway, your suggestion solves the problem. Thanks a lot Smiley Very Happy

0 Kudos
Message 5 of 5
(15,408 Views)