Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос по custom variant [D7, WinXP]


Страницы:   1 2 3

oxffff ©   (2006-07-06 13:40:00) 

Версия Delphi 7.

Изучаю возможность создания пользовательских variant.
Есть неплохой (но странный пример) TComplexVariantType из модуля VarCmplx.
Если посмотреть на реализацию метода copy

procedure TComplexVariantType.Copy(var Dest: TVarData; const Source: TVarData;
 const Indirect: Boolean);
begin
 if Indirect and VarDataIsByRef(Source) then
    VarDataCopyNoInd(Dest, Source)
 else
   with TComplexVarData(Dest) do
   begin
     VType := VarType;
     VComplex := TComplexData.Create(TComplexVarData(Source).VComplex);
   end;
end;

При byref варианте происходит вызов VarDataCopyNoInd

В help про него написано

Unlike the VarDataCopy method, it can’t handle data that is stored indirectly (when the VType field includes varByRef)

Но бог с ним. Посмотрев на исходники можно убедится, что он
и byref variant пытается обработать вызвав внутри VarCopyByRef.
Смотрим дальше, если variant custom то происходит вызов VarCopyNoIndDeep. а там опять вызов
LSourceHandler.Copy(Dest, Source, True). Таким образом должно происходить зацикливание. Но оно не будет происходить по одной простой причине. FindCustomVariantType не работает с
byref custom variant.

Таким образом нельзя создать пользовательский byref variant.
+ некорректное описание VarDataCopyNoInd.

Вообщем кто понял о чем я тут говорю, может выскажится.
Заранее благодарен.


oxffff   (2006-07-11 22:56:00) [21]

:). Приношу извинения. А как добавить в пост?


Суслик   (2006-07-11 22:12:00) [22]

эттта, автор, ну научись посты оформлять.
это тебе не чат.


oxffff   (2006-07-11 21:41:00) [23]

unit VarUtils

const
{$IFDEF MSWINDOWS}
 GenericVarUtils = False;
{$ELSE}
 GenericVarUtils = True;
{$ENDIF}

 GenericVariants = GenericVarUtils;

{$IF not GenericVariants}
procedure VariantInit; external oleaut name 'VariantInit';
function VariantClear; external oleaut name 'VariantClear';
function VariantCopy; external oleaut name 'VariantCopy';
function VariantCopyInd; external oleaut name 'VariantCopyInd';
function VariantChangeType; external oleaut name 'VariantChangeType';

{$ELSE}
................
Таким образом VariantCopy используется из oleaut32.dll

Но VariantCopy к теме не относится.


oxffff   (2006-07-11 21:02:00) [24]

Что касаемо VariantCopy.
То до нее дело не должно вообще недоходить при грамотной реализации.

Ваши соображения REA.

Это особенность или ...


oxffff   (2006-07-11 21:00:00) [25]

VarCopyNoInd ->VarCopyNoIndDeep->FindCustomVariantType
                                                  LSourceHandler.Copy(Dest, Source, True)

Так что и он неправильно отработает.


oxffff   (2006-07-11 20:58:00) [26]

Должен тоже копировать некорректно VarCopyNoInd  
поскольку внутри вызывает  FindCustomVariantType.
Который By ref custom не обрабатывает.


oxffff   (2006-07-11 20:00:00) [27]

Используется API функция VariantCopy


oxffff   (2006-07-11 18:44:00) [28]

Хотя это интересно.  

{$IF not GenericVariants}
procedure VariantInit; external oleaut name 'VariantInit';
function VariantClear; external oleaut name 'VariantClear';
function VariantCopy; external oleaut name 'VariantCopy';
function VariantCopyInd; external oleaut name 'VariantCopyInd';
function VariantChangeType; external oleaut name 'VariantChangeType';

{$ELSE}


oxffff   (2006-07-11 18:44:00) [29]

Хотя это интересно.  

{$IF not GenericVariants}
procedure VariantInit; external oleaut name 'VariantInit';
function VariantClear; external oleaut name 'VariantClear';
function VariantCopy; external oleaut name 'VariantCopy';
function VariantCopyInd; external oleaut name 'VariantCopyInd';
function VariantChangeType; external oleaut name 'VariantChangeType';

{$ELSE}


oxffff   (2006-07-11 18:36:00) [30]

VariantCopy это же API функция.
Хотя в VarUtils тоже есть такая функция. Интересно.


REA   (2006-07-11 17:35:00) [31]

Кстати кое что они пофиксили (я сам удивился когда код смотрел):
http://qc.borland.com/wc/qcmain.aspx?d=9619


REA   (2006-07-11 17:31:00) [32]

Это из VariantCopy (VarUtils), но это все равно мало что дает - вылетает ошибка.

А вот _VarCopyNoInd похоже корректно копирует var by ref, но как заставить компилятор вызвать ее, а не _VarCopy?
Можно и вручную конечно...


oxffff   (2006-07-11 17:25:00) [33]

Это откуда
if (Source.VType and varByRef) <> 0 then // var is byref
        Dest.VPointer := Source.VPointer


oxffff   (2006-07-11 17:22:00) [34]

Не понял?


REA   (2006-07-11 17:08:00) [35]

Все так. FindCustomVariantType не найдет custom variant by ref и вызвался бы VariantCopy, где

       if (Source.VType and varByRef) <> 0 then // var is byref
         Dest.VPointer := Source.VPointer

но на VariantClear вываливается invalid variant type

А когда вызывается _VarCopyNoInd? Это вроде тоже должен компилятор генерировать.


oxffff   (2006-07-11 16:11:00) [36]

То есть еще раз поясню.

procedure Some(A:variant);
var b:variant;
begin
b:=A; // будет вызов varcopy
end;

Реализация varcopy.
При custom variant varcopy вызовет VarCopyDeep.

А там такие строчки

// otherwise try for custom
else if FindCustomVariantType(Source.VType, LSourceHandler) then
  LSourceHandler.Copy(Dest, Source, False)

Ищем класс обертку с помощью FindCustomVariantType и далее
вызывает у него метод copy.
Но !!!
1.  FindCustomVariantType не найдет custom variant by ref.
Почему?
А вот почему. Его реализация

Result := (LVarTypes <> nil) and
          (AVarType >= CMinVarType) and (AVarType <= CMaxVarType);
if Result then .....

2. Даже если бы и нашел, то вызов был LSourceHandler.Copy(Dest, Source,False)
 А это если посмотреть
procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean): virtual; abstract;

INDIRECT=FALSE

Теперь понятно о чем я


oxffff   (2006-07-11 16:06:00) [37]

то есть по help

VarDataCopyNoInd.

Unlike the VarDataCopy method, it can’t handle data that is stored indirectly (when the VType field includes varByRef).

А он вызывается для by ref custom. Что нестыковка в help.

И самое главное еще раз

То есть если есть конструкция такая

procedure Some(A:variant);
var b:variant;
begin
b:=A; // будет вызов varcopy
end;

_VarCopy->VarCopyDeep->FindCustomVariantType !!!
                                ->LSourceHandler.Copy(Dest, Source, False) !!!

FindCustomVariantType  не найдет byref custom variant
и Copy(Dest, Source, False) вызовется как DIRECT. В не зависимости от
того DIRECT или INDIRECT


oxffff   (2006-07-11 15:59:00) [38]

Это то да.
Но во первых FindCustomVariantType не найдет byref custom


REA   (2006-07-11 15:01:00) [39]

Copy->VarDataCopyNoInd->_VarCopyNoInd->VarCopyByRef->VarCopyNoIndDeep

procedure VarCopyNoIndDeep(var Dest: TVarData; const Source: TVarData);
...
 if FindCustomVariantType(Source.VType, LSourceHandler) then
   LSourceHandler.Copy(Dest, Source, True)

тут то как раз True


oxffff   (2006-07-11 13:44:00) [40]

Реализация varcopy.
При custom variant varcopy вызовет VarCopyDeep.

А там такие строчки

 // otherwise try for custom
 else if FindCustomVariantType(Source.VType, LSourceHandler) then
   LSourceHandler.Copy(Dest, Source, False)

Ищем класс обертку с помощью FindCustomVariantType и далее
вызывает у него метод copy.
Но !!!
1.  FindCustomVariantType не найдет custom variant by ref.
Почему?
А вот почему. Его реализация

 Result := (LVarTypes <> nil) and
           (AVarType >= CMinVarType) and (AVarType <= CMaxVarType);
 if Result then .....

2. Даже если бы и нашел, то вызов был LSourceHandler.Copy(Dest, Source,False)
  А это если посмотреть
procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean): virtual; abstract;

INDIRECT=FALSE

Читаем help.

Indirect indicates whether the copy is direct or indirect. When Indirect is true, the source TVarData record contains an indirect reference to its data (the VarDataIsByRef method should return true for Source). When making an indirect copy, it is not necessary to reallocate records or objects, because the Variant does not “own” the data, it merely points to it. When making a direct copy, Copy must allocate new memory for any allocated records or objects, so that Dest can “own” its own copy of the data.

   А это значит. Что копирование для custom variant - DIRECT.

REA
Вообще то не Custom Variant не работает с variant by ref, а только TComplexVariantType (да и то еще не уверен).

Не понял.

procedure TComplexVariantType.Copy(var Dest: TVarData; const Source: TVarData;
const Indirect: Boolean);
begin
if Indirect and VarDataIsByRef(Source) then
  VarDataCopyNoInd(Dest, Source)
else
  with TComplexVarData(Dest) do
  begin
    VType := VarType;
    VComplex := TComplexData.Create(TComplexVarData(Source).VComplex);
  end;
end;

Это было бы правильно если бы FindCustomVariantType работал с by ref.

И еще

Для
TComplexVariantType.Copy

При byref варианте происходит вызов VarDataCopyNoInd

В help про него написано

Unlike the VarDataCopy method, it can’t handle data that is stored indirectly (when the VType field includes varByRef)


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо