Форум: "Основная";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
ВнизВопрос по custom variant Найти похожие ветки
← →
oxffff © (2006-07-06 13:40) [0]Версия 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.
Вообщем кто понял о чем я тут говорю, может выскажится.
Заранее благодарен.
← →
Суслик © (2006-07-10 02:34) [1]выскажусь не совсем по теме, но тебе может поможет.
я сам с этими вариантами разбирался - завернуто там очень.
но есть хорошая новость - в delphi2006 в записи можно добавлять методы и перегрузку операторов. При этом это делается очень легко.
так что если тебе нужно создать какой-то специфический тип, то можно использовать новые возможности записей (в справке они называеются advanced records).
← →
REA (2006-07-10 10:24) [2]Поддержжу - ну их нафиг эти варианты.
← →
oxffff © (2006-07-10 20:09) [3]Правда только New for Delphi Win32! Operator overloading.
Исключительно для .NET
← →
oxffff © (2006-07-10 20:12) [4]Это из FEATURE MATRIX.
Borland® Developer Studio 2006
Includes Borland® Delphi® 2006, C++Builder® 2006, and C#Builder® 2006
FEATURE MATRIX
Правда только New for Delphi Win32! Operator overloading.
Исключительно для .NET
Что касаемо вопроса меня смутила реализация в Delphi 7.
И описания в help.
← →
oxffff © (2006-07-10 20:14) [5]New for Delphi Win32! Records with methods (value types).
Тоже для .NET и #
← →
oxffff © (2006-07-10 20:17) [6]Что касаемо custom variant by ref. То нормальными средствами это не реализуется :). Конечно выкрутися можно.
Просто хотел обратить внимание общественности на данную особенность.
← →
oxffff © (2006-07-10 20:24) [7]То есть если есть конструкция такая
procedure Some(A:variant);
var b:variant;
begin
b:=A;
end;
И если A - custom variant by ref. То вывалиться exception.
Проблема в реализации VarCopyDeep и в реализации FindCustomVariantType.
Модуль variants.
Применительно для DElphi 7.
← →
Суслик © (2006-07-10 23:29) [8]по custom variantam ты вряд ли что -то тут найдешь.
я несколько раз спрашивал - ответ тишина.
есть ощущение, что ими никто не пользуется...
← →
Германн © (2006-07-11 03:20) [9]
> по custom variantam ты вряд ли что -то тут найдешь. я несколько
> раз спрашивал - ответ тишина. есть ощущение, что ими никто
> не пользуется...
Ну если у МАСТЕРОВ Д7 есть только дома и только вечером. И то не у всех (имхо), и то неизвестно для чего, то спрашивать придётся у Сергея Орлика. А он отвечает тут только по тем вопросам, которые связаны с политикой фирмы. Имхо. :-)
← →
REA (2006-07-11 09:55) [10]Вообще то не Custom Variant не работает с variant by ref, а только TComplexVariantType (да и то еще не уверен). В остальных случаях ничто не мешает перекрыть Copy и делать все что угодно.
← →
REA (2006-07-11 10:00) [11]А почему FindCustomVariantType не работает с byref custom variant?
Что то у меня не создалось такого впечатления. Там вообще byref не фигурирует - на входе код варианта, на выходе класс.
← →
oxffff © (2006-07-11 13:44) [12]Реализация 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)
← →
REA (2006-07-11 15:01) [13]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 15:59) [14]Это то да.
Но во первых FindCustomVariantType не найдет byref custom
← →
oxffff © (2006-07-11 16:06) [15]то есть по 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 16:11) [16]То есть еще раз поясню.
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
Теперь понятно о чем я
← →
REA (2006-07-11 17:08) [17]Все так. 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 17:22) [18]Не понял?
← →
oxffff © (2006-07-11 17:25) [19]Это откуда
if (Source.VType and varByRef) <> 0 then // var is byref
Dest.VPointer := Source.VPointer
← →
REA (2006-07-11 17:31) [20]Это из VariantCopy (VarUtils), но это все равно мало что дает - вылетает ошибка.
А вот _VarCopyNoInd похоже корректно копирует var by ref, но как заставить компилятор вызвать ее, а не _VarCopy?
Можно и вручную конечно...
← →
REA (2006-07-11 17:35) [21]Кстати кое что они пофиксили (я сам удивился когда код смотрел):
http://qc.borland.com/wc/qcmain.aspx?d=9619
← →
oxffff © (2006-07-11 18:36) [22]VariantCopy это же API функция.
Хотя в VarUtils тоже есть такая функция. Интересно.
← →
oxffff © (2006-07-11 18:44) [23]Хотя это интересно.
{$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) [24]Хотя это интересно.
{$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 20:00) [25]Используется API функция VariantCopy
← →
oxffff © (2006-07-11 20:58) [26]Должен тоже копировать некорректно VarCopyNoInd
поскольку внутри вызывает FindCustomVariantType.
Который By ref custom не обрабатывает.
← →
oxffff © (2006-07-11 21:00) [27]VarCopyNoInd ->VarCopyNoIndDeep->FindCustomVariantType
LSourceHandler.Copy(Dest, Source, True)
Так что и он неправильно отработает.
← →
oxffff © (2006-07-11 21:02) [28]Что касаемо VariantCopy.
То до нее дело не должно вообще недоходить при грамотной реализации.
Ваши соображения REA.
Это особенность или ...
← →
oxffff © (2006-07-11 21:41) [29]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 к теме не относится.
← →
Суслик © (2006-07-11 22:12) [30]эттта, автор, ну научись посты оформлять.
это тебе не чат.
← →
oxffff © (2006-07-11 22:56) [31]:). Приношу извинения. А как добавить в пост?
← →
REA (2006-07-12 10:56) [32]Да я проверил - вызывается и вылетает. (см. выше)
А вот как вызвать _VarCopyNoInd средствами компилятора (если написать := то вызовется _VarCopy, может другое заклятие есть)?
Она вроде должна ByRef обрабатывать.
Не исключено что в 2006 исправили это, хотя Custom var by ref экзотика.
В Delphi вообще экономят на реализациях как с API так и библиотеками классов и т.п.
← →
oxffff © (2006-07-12 12:07) [33]Да вот такая экзотика. :)
Но дело в том, что если написать VarCopyNoInd(a,b).
Где source - custom variant by ref.
То и этом случае вылетит ошибка поскольку FindCustomVariantType
не найдет by ref custom.
Уважаемый REA благодарю за диалог.
Сейчас осталось найти 2006. Недорого ;)
← →
REA (2006-07-12 12:37) [34]А там похоже тоже самое - я посмотрел.
Есть возможность создавать CustomVariant с заданным типом (т.е. выставить бит ByRef) и тогда не исключено, что FindCustomVariantType отработает.
constructor Create(RequestedVarType: TVarType); overload;
← →
oxffff © (2006-07-12 12:49) [35]попробуй сделать так
var a,b:variant;
begin
tvardata(a).VType:=273 or varByRef;
VarCopyNoInd(b,a);
Все равно ошибка на FindCustomVariantType
273 - пользовательский custom
← →
oxffff © (2006-07-12 12:51) [36]Точнее ошибка на API VariantCopyInd.
До которой дело вообще не должно доходить.
Но из-за FindCustomVariantType доходит.
← →
oxffff © (2006-07-12 12:58) [37]Ошибка в FindCustomVariantType поскольку реализовано некорректное сравнение.
function FindCustomVariantType(const AVarType: TVarType; out CustomVariantType: TCustomVariantType): Boolean;
begin
// fail if no custom types are defined or if the vartype is way out of range
Result := (LVarTypes <> nil) and
(AVarType >= CMinVarType) and (AVarType <= CMaxVarType);
........
// здесь ошибка
(AVarType >= CMinVarType) and (AVarType <= CMaxVarType);
А вот если было так, то работало бы
(AVarType AND (NOT VARBYREF))>= CMinVarType and
(AVarType AND (NOTVARBYREF))<=CMaxVarType)
← →
REA (2006-07-13 10:13) [38]см. [34] - я имел ввиду, что AVarType уже может содержать бит byref но тогда вероятно тип будет все же вне CMinVarType - CMaxVarType и не зарегистрируется.
← →
oxffff © (2006-07-13 13:02) [39]Так при регистрации сustom variant и не нужно устанавливать byref.
Этот бит же указывает на передачу данных по ссылке.
Так есть еще и бит varArray.
varByRef, varArray эти биты не нужно устанавливать при регистрации пользовательского варианта.
varArray = $2000;
varByRef = $4000;
А вот найти FindCustomVariantType его не сможет поскольку нужно перед сравнением применимь маску. А именно varTypeMask
varTypeMask=$0FFF;
Поэтому для обработки varByRef и varArray
см. [37]
(AVarType AND varTypeMask)>= CMinVarType and
(AVarType AND varTypeMask)<=CMaxVarType)
Уважаемый REA.
Снабдите ссылкой на borland куда задать такого рода вопрос.
← →
Суслик © (2006-07-13 14:38) [40]только news группы. http://newsgroups.borland.com
все вопросы "на борланде" задаются именно здесь.
он, правда, сейчас что-то не открывается. но это за мою память с ним впервые такое.
выбери news группу, связанную с компилятором.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.043 c