![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос по custom variant [D7, WinXP]
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)