Tuesday, February 05, 2008

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)
 if (*fileData != NULL)
  TCHAR msg[128];
  _stprintf(msg, "Received %lu byte array, destroying it and reallocating", (*fileData)->rgsabound[0].cElements);
  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;
 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

  • 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

No comments: