2013-04-30 4 views
2

Использование Delphi, мне нужно получить доступ к OleVariant, содержащему одну или несколько записей в массиве.Доступ к OleVariant, содержащий VT_ARRAY из VT_RECORD из Delphi

Метод I вызов возвращает VT_ARRAY из VT_RECORD, а сами записи определяются как:

struct StreamTimeInfo { 
    unsigned int PID; 
    LONGLONG PTS; 
    LONGLONG TimeStamp; 
}; 

Мой код выглядит так:

procedure Test; 
type 
    TStreamInfo = record 
    PID: Cardinal; 
    PTS: Int64; 
    TimeStamp: Int64; 
    end; 
var 
    Value: OleVariant 
    StreamTime: TStreamInfo; 
begin 
    GetValue(Value); // Value holds a VT_ARRAY of VT_RECORD 

    // How should I access the array of records in Delphi? 
    // I've tried this to get to the first element: 
    StreamTime := TStreamInfo(TVarData(Value).VPointer^); 
end; 

Я не понимаю, как получить доступ к записи из Delphi.

Любой ввод очень ценится.

+0

Я пробовал как упакованный/не упакованную запись, никакой разницы. Кроме того, код 32-разрядный (Delphi и DLL, я звоню). – TomRay74

+0

Исходный код не использует #pragma pack 1, поэтому я удалил упакованный. – TomRay74

ответ

3

Я никогда не делал этого раньше, но я думаю, что это должно сработать.

type 
    TStreamInfoArray = array [0..MaxArrayCount-1] of TStreamInfo; 
    PStreamInfoArray = ^TStreamInfoArray; 
var 
    Value: Variant; 
    p: PStreamInfoArray; 
    StreamInfo: TStreamInfo; 
begin 
    GetValue(Value); 
    p := PStreamInfoArray(VarArrayLock(Value)); 
    try 
    StreamInfo := p^[Index]; 
    finally 
    VarArrayUnlock(Value); 
    end; 
end; 
+0

Дэвид, Удивительный! Ваш код работает отлично. Я немного смущен, что сам не понял этого. Спасибо! – TomRay74

+0

Я так же изумлен, как и вы! На самом деле проблема упаковки имеет значение и на 32-х битках, не так ли. У записи есть пробел после 'PID'. –

+0

Я хотел бы обновить этот вопрос с помощью моего окончательного кода для дальнейшего использования и в качестве ссылки для других. Должен ли я редактировать существующую запись или добавлять ответ самостоятельно? Каков предпочтительный способ сделать это? – TomRay74

2

Для дальнейшего использования и для других, вот окончательный рабочий код:

// Original C-Source definition of StreamTimeInfo 
// import "oaidl.idl"; 
// import "ocidl.idl"; 
// [uuid(A5AA2ACD-BEA0-4570-9232-D8301A6DAE0F)] 
// struct StreamTimeInfo { 
// unsigned int PID;  
// LONGLONG  PTS;  
// LONGLONG  TimeStamp; 
// }; 
// cpp_quote("typedef struct StreamTimeInfo StreamTimeInfo;") 

procedure GetStreamTimes; 
type 
    TStreamTimeInfo = record 
    PID: Cardinal; 
    PTS: Int64; 
    TimeStamp: Int64; 
    end; 
    TStreamTimeInfoArray = array[0..31] of TStreamTimeInfo; 
    PStreamTimeInfoArray = ^TStreamTimeInfoArray; 
var 
    Value: OleVariant; 
    SizeOfArray: Integer; 
    PtrToArray: PStreamTimeInfoArray; 
begin 
    GetValue(EMPGPDMX_STREAMTIMES, Value); 
    if VarArrayDimCount(Value) = 1 then 
    begin 
    SizeOfArray := 1 + VarArrayHighBound(Value, 1) - VarArrayLowBound(Value, 1); 
    PtrToArray := PStreamTimeInfoArray(VarArrayLock(Value)); 
    try 
    for I := 0 to SizeOfArray - 1 do 
    begin 
     StreamTimeInfo := PtrToArray^[I]; 
     // Usage Sample: 
     // FStatus.StreamTimePID[I] := StreamTimeInfo.PID; 
     // FStatus.StreamTimePTS[I] := StreamTimeInfo.PTS; 
     // FStatus.StreamTimeTS[I] := StreamTimeInfo.TimeStamp; 
    end; 
    finally 
    VarArrayUnlock(Value); 
    end; 
    end; 
end; 
+0

Ну, это на самом деле неправильно. Вы не хотите использовать 'VarArrayDimCount' таким образом. 'VarArrayDimCount' возвращает количество измерений. Итак, '0', если это не массив,' 1', если это 1D-массив, '2' для 2D-массива, скажем, матрица. Вы хотите проверить, что 'VarArrayDimCount' возвращает' 1'. А затем используйте '1 + VarArrayHighBound (Value, 1) -VarArrayLowBound (Value, 1)', чтобы найти количество элементов. –

+0

Doh! Вы абсолютно правы. Я обновил код. Не нужно тестировать VarArrayDimCount, поскольку я уже тестирую VarIsArray, и вызов GetValue() никогда не вернет многомерный массив. Благодаря! – TomRay74

+0

Я думаю, что я бы преобразовал 'VarIsArray' в' VarArrayDimCount (...) = 1', чтобы утверждать, что у вас нет мульти-мерного массива. Во всяком случае, я думаю, это было ценно для вас, чтобы опубликовать этот ответ! –

Смежные вопросы