Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.045 c
15-1154860777
PZ
2006-08-06 14:39
2006.09.03
День железнодорожника


15-1154714785
Eraser
2006-08-04 22:06
2006.09.03
Иконка 24x24, символизирующая просмотр видео.


15-1154623948
Petr V. Abramov
2006-08-03 20:52
2006.09.03
Система "Аллегро"


4-1147254508
QuickFinder
2006-05-10 13:48
2006.09.03
Определение операционной системы


4-1147205976
444ert666
2006-05-10 00:19
2006.09.03
TRAY-help!!!!!!!!!!!!!!!!





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский