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.