Я пытаюсь создать и прочитать SAFEARRAY (MyUDT) *, где MyUDT содержит SAFEARRAY, но когда я пытаюсь прочитать его, я получил исключение "Нарушение прав доступа".
Я определил следующую структуруи enum:
typedef [uuid(...)]
enum CollisionDetectorMoveType
{
CollisionDetectorMoveType_Unknown = -1,
CollisionDetectorMoveType_Move = 0,
CollisionDetectorMoveType_Measure
} CollisionDetectorMoveType;
typedef [uuid(...)]
struct CollisionDetectorXYZ
{
double X;
double Y;
double Z;
} CollisionDetectorXYZ;
typedef [uuid(...)]
struct CollisionDetectorMultiPosition
{
SAFEARRAY(CollisionDetectorXYZ) pos;
CollisionDetectorMoveType type;
} CollisionDetectorMultiPosition;
bool createTestCollisionDetectorMultiPositionSafeArray(SAFEARRAY** psa)
{
IRecordInfoPtr recordset_info = nullptr;
HRESULT hr = GetRecordInfoFromGuids(LIBID_CollisionDetectorLib, 1, 0, 0, UUID_CollisionDetectorMultiPosition, &recordset_info);
if (FAILED(hr))
{
return false;
}
SAFEARRAYBOUND safearray_bound;
memset(&safearray_bound, 0, sizeof(safearray_bound));
safearray_bound.cElements = 10;
safearray_bound.lLbound = 0;
*psa = ::SafeArrayCreateEx(VT_RECORD, 1, &safearray_bound, (PVOID)recordset_info);
for (size_t i = 0; i < 10; ++i)
{
CollisionDetectorMultiPosition multiPosition;
multiPosition.type = i % 2 == 0 ? CollisionDetectorMoveType_Move : CollisionDetectorMoveType_Measure;
if (!createTestCollisionDetectorXYZSafeArray(&multiPosition.pos))
{
return false;
}
LONG current_position = i;
::SafeArrayPutElement(*psa, ¤t_position, &multiPosition);
}
::SafeArrayUnaccessData(*psa);
return true;
}
}
bool createTestCollisionDetectorXYZSafeArray(SAFEARRAY** psa)
{
IRecordInfoPtr recordset_info = nullptr;
HRESULT hr = GetRecordInfoFromGuids(LIBID_CollisionDetectorLib, 1, 0, 0, UUID_CollisionDetectorXYZ, &recordset_info);
if (FAILED(hr))
{
return false;
}
SAFEARRAYBOUND safearray_bound;
memset(&safearray_bound, 0, sizeof(safearray_bound));
safearray_bound.cElements = 10;
safearray_bound.lLbound = 0;
*psa = ::SafeArrayCreateEx(VT_RECORD, 1, &safearray_bound, (PVOID)recordset_info);
for (size_t i = 0; i < 10; ++i)
{
CollisionDetectorXYZ current_point;
current_point.X = i;
current_point.Y = i;
current_point.Z = i;
LONG current_position = i;
::SafeArrayPutElement(*psa, ¤t_position, ¤t_point);
}
::SafeArrayUnaccessData(*psa);
return true;
}
Затем я пытаюсь создать и прочитать SAFEARRAY:
SAFEARRAY* psa2 = NULL;
if (!createTestCollisionDetectorMultiPositionSafeArray(&psa2))
{
*retVal = SYSERR;
return S_OK;
}
CollisionDetectorMultiPosition* current_pointer_to_element;
auto access_result = ::SafeArrayAccessData(psa2, (void **)¤t_pointer_to_element);
if (FAILED(access_result))
{
return S_OK;
}
LONG upper_bound, lower_bound;
::SafeArrayGetLBound(psa2, 1, &lower_bound);
::SafeArrayGetUBound(psa2, 1, &upper_bound);
std::vector<CollisionDetectorMultiPosition> multiPositionVector;
LONG size = upper_bound - lower_bound + 1;
for (LONG i = 0; i < size; i++)
{
CollisionDetectorMultiPosition this_value;
::SafeArrayGetElement(psa2, &i, (void *)&this_value);
multiPositionVector.push_back(this_value);
}
Однако, когда я вызываю :: SafeArrayGetElement (psa2, & i, (void *) & this_value);Я получил исключение.
Что я делаю не так?
Если я просто позвоню
CollisionDetectorMultiPosition multiPosition;
multiPosition.type = CollisionDetectorMoveType_Move;
if (!createTestCollisionDetectorXYZSafeArray(&multiPosition.pos))
{
*retVal = SYSERR;
return S_OK;
}
, я могу читать multiPosition.pos SAFEARRAY без проблем.
Спасибо за вашу помощь.
Решено
Я нашел решение, я сообщаю код для всех пользователей, которые могут иметь ту же проблему.По сути, дело в том, чтобы создать SAFEARRAY из VARIANT и заполнить структуру VARIANT с помощью CollisionDetectorMultiPosition.
CComVariant variant;
variant.vt = VT_RECORD;
variant.pvRecord = &multiPosition;
variant.pRecInfo = recordset_info;
Создание SAFEARRAY
bool createTestCollisionDetectorMultiPositionSafeArray(SAFEARRAY** psa)
{
IRecordInfoPtr recordset_info;
HRESULT hr = GetRecordInfoFromGuids(LIBID_CollisionDetectorLib, 1, 0, 0, UUID_CollisionDetectorMultiPosition, &recordset_info);
if (FAILED(hr))
{
return false;
}
SAFEARRAYBOUND safearray_bound;
memset(&safearray_bound, 0, sizeof(safearray_bound));
safearray_bound.cElements = 10;
safearray_bound.lLbound = 0;
*psa = SafeArrayCreate(VT_VARIANT, 1, &safearray_bound);
for (size_t i = 0; i < 10; ++i)
{
CollisionDetectorMultiPosition multiPosition;
multiPosition.type = i % 2 == 0 ? CollisionDetectorMoveType_Move : CollisionDetectorMoveType_Measure;
if (!createTestCollisionDetectorXYZSafeArray(&multiPosition.pos))
{
return false;
}
CComVariant variant;
variant.vt = VT_RECORD;
variant.pvRecord = &multiPosition;
variant.pRecInfo = recordset_info;
LONG current_position = i;
::SafeArrayPutElement(*psa, ¤t_position, &variant);
variant.vt = VT_EMPTY;
}
::SafeArrayUnaccessData(*psa);
return true;
}
Чтение SAFEARRAY
SAFEARRAY* psa2 = NULL;
if (!createTestCollisionDetectorMultiPositionSafeArray(&psa2))
{
*retVal = AC3SYSERR;
return S_OK;
}
LONG upper_bound, lower_bound;
::SafeArrayGetLBound(psa2, 1, &lower_bound);
::SafeArrayGetUBound(psa2, 1, &upper_bound);
std::vector<std::pair<CollisionDetectorMoveType, std::vector<CollisionDetectorXYZ>>> multiPositionVector;
LONG size = upper_bound - lower_bound + 1;
for (LONG i = 0; i < size; i++)
{
VARIANT this_value;
VariantInit(&this_value);
VariantClear(&this_value);
::SafeArrayGetElement(psa2, &i, (void *)&this_value);
CollisionDetectorMultiPosition* this_value2 = (CollisionDetectorMultiPosition *)this_value.pvRecord;
CollisionDetectorXYZ* current_pointer_to_element;
auto access_result = ::SafeArrayAccessData(this_value2->pos, (void **)¤t_pointer_to_element);
if (FAILED(access_result))
{
return S_OK;
}
LONG upper_bound, lower_bound;
::SafeArrayGetLBound(this_value2->pos, 1, &lower_bound);
::SafeArrayGetUBound(this_value2->pos, 1, &upper_bound);
std::vector<CollisionDetectorXYZ> moves;
LONG size = upper_bound - lower_bound + 1;
for (LONG i = 0; i < size; i++)
{
CollisionDetectorXYZ this_value;
::SafeArrayGetElement(this_value2->pos, &i, (void *)&this_value);
moves.push_back(this_value);
}
multiPositionVector.push_back(std::make_pair(this_value2->type, moves));
::SafeArrayUnaccessData(this_value2->pos);
}