Как уже упоминали другие в комментариях, вы не можете передать необработанный массив таким образом.Как минимум, вы должны скопировать байтовый массив в SAFEARRAY
байтов (SAFEARRAY(BYTE)
в IDL).Я только что проверил приведенный ниже код с помощью собственного прокси / заглушки (скомпилированного из кода P / S, сгенерированного midl.exe), и я смог получить данные по сети.
Если вы хотите использоватьстандартный P / S, такой как PSDispatch
({00020420-0000-0000-C000-000000000046}
) или PSOAInterface
({00020424-0000-0000-C000-000000000046}
), или, если вы хотите использовать VBA в качестве клиента, вам, возможно, придется преобразовать это в SAFEARRAY(VARIANT)
и /или поместите получившийся защитный луч в VARIANT
.Попробуйте самый простой подход - сначала просто используйте SAFEARRAY(BYTE)
, потому что это тот, который требует наименьших затрат.(A SAFEARRAY(VARIANT)
использует в 16 раз больше памяти, чем SAFEARRAY(BYTE)
, потому что VARIANT
имеет длину 16 байтов. И вам придется вручную преобразовывать каждый байт в VARIANT
, в отличие от простых вызовов memcpy
покажите ниже.)
Упаковка байтового массива в SAFEARRAY
: (Обратите внимание, что это копирует байтовый массив в SAFEARRAY
. Вы можете разбираться с внутренними элементами SAFEARRAY
struct для предотвращения копирования, но вы будете делать что-то нестандартным образом.)
/// <summary>Packs an array of bytes into a SAFEARRAY.</summary>
/// <param name="count">The number of bytes.</param>
/// <param name="pData">A reference to the byte array. Not read if count is 0.</param>
/// <param name="pResult">Receives the packed LPSAFEARRAY on success.</param>
HRESULT PackBytes(ULONG count, const BYTE* pData, /*[ref]*/ LPSAFEARRAY* pResult)
{
// initialize output parameters
*pResult = NULL;
// describe the boundaries of the safearray (1 dimension of the specified length, starting at standard index 1)
SAFEARRAYBOUND bound{ count, 1 };
// create the safearray
LPSAFEARRAY safearray = SafeArrayCreate(VT_UI1, 1, &bound);
if (!safearray)
return E_OUTOFMEMORY;
// when there is actually data...
if (count > 0)
{
// begin accessing the safearray data
BYTE* safearrayData;
HRESULT hr = SafeArrayAccessData(safearray, reinterpret_cast<LPVOID*>(&safearrayData));
if (FAILED(hr))
{
SafeArrayDestroy(safearray);
return hr;
}
// copy the data into the safearray
memcpy(safearrayData, pData, count);
// finish accessing the safearray data
hr = SafeArrayUnaccessData(safearray);
if (FAILED(hr))
{
SafeArrayDestroy(safearray);
return hr;
}
}
// set output parameters
*pResult = safearray;
// success
return S_OK;
}
Распаковка байтового массива из SAFEARRAY
: (Примечаниечто это копирует байтовый массив из SAFEARRAY
. Вы можете поиграться с внутренностями структуры SAFEARRAY
, чтобы предотвратить копирование, но вы будете делать что-то нестандартным образом. Также вы можете выбратьиспользуйте данные непосредственно из SAFEARRAY
, указав код потребления между SafeArrayAccessData
и SafeArrayUnaccessData
.)
/// <summary>Unpacks an array of bytes from a SAFEARRAY.</summary>
/// <param name="safearray">The source SAFEARRAY.</param>
/// <param name="pCount">A pointer to a ULONG that will receive the number of bytes.</param>
/// <param name="ppData">A pointer to a BYTE* that will receive a reference to the new byte array.
/// This array must be deallocated (delete []) when the caller is done with it.</param>
HRESULT UnpackBytes(LPSAFEARRAY safearray, /*[out]*/ ULONG* pCount, /*[out]*/ BYTE** ppData)
{
// initialize output parameters
*pCount = 0;
*ppData = NULL;
// validate the safearray element type (must be VT_UI1)
VARTYPE vartype;
HRESULT hr = SafeArrayGetVartype(safearray, &vartype);
if (FAILED(hr))
return hr;
if (vartype != VT_UI1)
return E_INVALIDARG;
// validate the number of dimensions (must be 1)
UINT dim = SafeArrayGetDim(safearray);
if (dim != 1)
return E_INVALIDARG;
// get the lower bound of dimension 1
LONG lBound;
hr = SafeArrayGetLBound(safearray, 1, &lBound);
if (FAILED(hr))
return hr;
// get the upper bound of dimension 1
LONG uBound;
hr = SafeArrayGetUBound(safearray, 1, &uBound);
if (FAILED(hr))
return hr;
// if the upper bound is less than the lower bound, it's an empty array
if (uBound < lBound)
return S_OK;
// calculate the count of the bytes
ULONG count = uBound - lBound + 1;
// create buffer
BYTE* pData = new BYTE[count];
if (!pData)
return E_OUTOFMEMORY;
// begin accessing the safearray data
BYTE* safearrayData;
hr = SafeArrayAccessData(safearray, reinterpret_cast<LPVOID*>(&safearrayData));
if (FAILED(hr))
{
delete[] pData;
return hr;
}
// copy the data
memcpy(pData, safearrayData, count);
// finish accessing the safearray data
hr = SafeArrayUnaccessData(safearray);
if (FAILED(hr))
{
delete[] pData;
return hr;
}
// set output parameters
*pCount = count;
*ppData = pData;
// success
return S_OK;
}