Gert Lombard's Blog     About     Archive     Feed
My passion is code quality, automated testing, software craftsmanship.

Returning a byte array from C++ to Visual Basic 6

I had to figure out how to return a byte array from a C++ DLL to VB6 (using unmanaged C++ in Visual Studio 2005).

This is the general idea:

__declspec(dllexport) int __stdcall modifyArrayTest(SAFEARRAY** fileData)
{
HRESULT hr;
SAFEARRAYBOUND bound[1];
if (*fileData != NULL)
{
TCHAR msg[128];
_stprintf(msg, "Received %lu byte array, destroying it and reallocating", (*fileData)->rgsabound[0].cElements);
OutputDebugString(msg);
SafeArrayDestroy(*fileData);
}
else
{
OutputDebugString("Received null array, reallocating");
}
bound[0].cElements = 10; // 10 byte array
bound[0].lLbound = 0;
*fileData = SafeArrayCreate(VT_UI1, 1, bound);
hr = SafeArrayLock(*fileData);
if (hr)
{
OutputDebugString("SafeArrayLock failed");
return -1;
}
unsigned char *data = (unsigned char*)(*fileData)->pvData;
for (int n = 0; n < 10; n++)
{
data[n] = n;
}
SafeArrayUnlock(*fileData);
return 0;
}


Now the function is imported as follows in VB6:

Private Declare Function modifyArrayTest _
Lib "ArrayTest.dll" (ByRef a() As Byte) As Long


And used like this:

Dim data() as Byte
Dim returnedBytes as Long
Call modifyArrayTest(data)
returnedBytes = UBound(data) + 1


Notes:
  • I found it useful to use OutputDebugString to log debug messages in my DLL code and then using DebugView from SysInternals to view the messages.
  • I noticed the DLL has to be compiled using ANSI (i.e. Character Set = Not Set) instead of Unicode (the default) to be able to pass strings back to VB6.
Reference: VB5DLL.TXT