LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

c function wrappers in C++ Object DLL

I have an extensive codebase written in C++ that I would like to be able to access in Labview. In order to access my c++ code I have started DLL projects in Visual Studio, and have created an export file per project which simply wraps the C++ class into a bunch of function calls.

One example is a USB Driver I have written. I have created a new file named USBExports.cpp. Within this file are simply wrapper functions ( with extern "C" to avoid the name mangling problem ) that take a uint32 as a reference to a C++ object, and then take the rest of the function parameters

for instance:

class USB_A11
{
USB_A11();
// Bulk read
unsigned int Read( char* buffer, int lengthToRead );
// Bulk write
unsigned int Write( char* buffer, int lengthToWrite );
};


The wrapper functions would be as follows:

extern "C"
{
_declspec(dllexport) unsigned int CreateUSB_A11();
_declspec(dllexport) unsigned int Read( unsigned int USB_Handle, char* buffer, int lengthToRead );
_declspec(dllexport) unsigned int Write( unsigned int USB_Handle, char* buffer, int lengthToWrite );
_declspec(dllexport) void Close( unsigned int USB_Handle );
}

where the definitions are as follows:

_declspec(dllexport) unsigned int CreateUSB_A11()
{
try
{
USB_A11 *usbConnection = new USB_A11();
return (void*)usbConnection;
}
catch(...)
{
return 0;
}
}

_declspec(dllexport) void Close( unsigned int USB_Handle )
{
try
{
USB_A11 *usbConnection = (USB_A11)USB_Handle;
if( usbConnection != NULL )
{
usbConnection->Close();
delete usbConnection;
}
}
catch(...)
{}
}

_declspec(dllexport) unsigned int Read( unsigned int USB_Handle, char* buffer, int lengthToRead )
{
try
{
USB_A11 *usbConnection;
usbConnection = ((USB_A11)USB_Handle);

return usbConnection->Read( buffer, lengthToRead );
}
catch(...)
{
return 0;
}
}

//... And similarly for write.


Notice that CreateUSB_A11 dynamically creates an object on the heap, and returns a reference to that object. Also notice the Close() call will delete the reference to the object.



This basically works. And in fact I can open a connection, write to it, read from it and then close it. In fact I can do it multiple times in a row. But strangely, it sometimes decides not to work. Any thoughts to why? The c++ code has been running in several applications for years and works just fine. Is there anything weird about allocatin space on the heap in this manner? Does labview support this?

When it crashes it is due to an ACCESS Violation from LabView.exe. I have a debug project running and have tested to make sure that it is not occuring within my DLL, and my DLL never crashes.


P.S. As well I have included the function

BOOL APIENTRY DllMain( HANDLE /*hModule*/,
DWORD ul_reason_for_call,
LPVOID /*lpReserved*/
)

I found that this allowed the object to retain state after each DLL call.
0 Kudos
Message 1 of 3
(3,167 Views)
I forgot to mention one thing. I have wrapped each of these DLL calls into their own VI, and I have a USB.llb that holds each of these vis. I have also made each of the sub vis reentrant.
0 Kudos
Message 2 of 3
(3,165 Views)
Hi Alan,

Are you sure that the DLL is thread-safe? By setting the Call Library Function node to reentrant, you are indicating that the DLL can be called from multiple threads at the same time. Oftentimes, when accessing hardware interfaces, there can only ever be one open reference to that hardware reference at a time.

It could be that in most cases the multiple calls to the DLL are not happening at the same time and therefore the program doee not crash. However there might be times when the first call to the DLL is not finishing the cleanup routine when another DLL call may be initiating. This will then result in memory space being corrupted and LabVIEW will crash.

Try changing the DLL to "Run in UI Thread" rather than Reentrant and see if that makes a difference.

Best of luck!

Kileen
0 Kudos
Message 3 of 3
(3,155 Views)