Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.11;
Скачать: [xml.tar.bz2];




Вниз

Помогите преобращовать Record в Variant! 


Last Hero   (2002-02-19 21:38) [0]

Проблема. Нужно преобразовать переменную типа Record в Variant. Существует очень много статей, как это сделать с массивами, картинками, бинарной информацией, но нигде не нашел, как преобразовать Record.
Помогите!!!!!!!!



Last Hero   (2002-02-20 08:26) [1]

Ответьте!!! Please...
Как можно преобразовать Record в Variant Array? И можно ли? А также обратно преобразовать в Record... И, пожалуйста, просто пример кода!!!



Digitman   (2002-02-20 08:51) [2]

никак. переменные вариантного типа не поддерживают автоматическое управление распределением памяти под пользовательские типы данных



SEM   (2002-02-20 10:39) [3]

Может я не понял вопроса, но может быть спасет
функция VarArrayCreate, с помощью которой можно создать
массив байтов примерно так:
V: Variant;
...
V := VarArrayCreate([...], varByte);

И копирнуть туда record.



Юрий Федоров   (2002-02-20 11:04) [4]

И для копирования использовать VarArrayLock, VarArrayUnLock



Last Hero   (2002-02-20 13:57) [5]

>SEM © and Юрий Федоров ©
Именно это я и имел в виду, пожалуйста, приведите пример, как это можно сделать?



Набережных С.   (2002-02-20 16:21) [6]

Посмотри
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=9090



Last Hero   (2002-02-20 20:24) [7]

Сделал все так, как в примере...

Я таким образом пытаюсь передать данные на сервер приложений (MIDAS)...

Все нормально компилится, как будто работает (то есть в данных в примере строчках кода никаких exception нет), но при попытке обращения на сервере к любому из полей рекорда появляется Access Violation :-(

Как это может быть?



Набережных С.   (2002-02-20 21:32) [8]

Покажи код



Last Hero   (2002-02-20 23:00) [9]

Запись (в TLB, экспортирую и в сервер и в клиент):

StudentRecord = packed record
ID: Integer;
Main: MainStudentRecord;
Address: AddressRecord;
Passport: PassportRecord;
Reference: ReferenceRecord;
MainSchool: SchoolRecord;
MainCollege: CollegeRecord;
MainGraduate: GraduateRecord;
MainMaster: MasterRecord;
MainAdditional: AdditionalRecord;
MainDriver: DriverRecord;
language1: LanguageRecord;
language2: LanguageRecord;
language3: LanguageRecord;
language4: LanguageRecord;
language5: LanguageRecord;
Work1: WorkRecord;
Work2: WorkRecord;
Work3: WorkRecord;
Work4: WorkRecord;
Work5: WorkRecord;
knollege: WideString;
notes: WideString;
end;

MainStudentRecord = packed record
Photo: OleVariant;
FirstName: WideString;
SecondName: WideString;
LastName: WideString;
Birthday: TDateTime;
Sex: Integer;
FamilyStatus: Integer;
Military: Integer;
end;
// Далее различные рекорды, на которые ссылается StudentRecord


Клиент:

var StudData : StudentRecord;
StudOle : OleVariant;
PStudData : Pointer;
//..........................................................
// Здесь заполняется StudData значениями, которые я хочу послать на сервер
//..........................................................
StudOle := VarArrayCreate([0, SizeOf(StudentRecord)], varByte);
PStudData := VarArrayLock(StudOle);
try
Move(StudData, PStudData^, SizeOf(StudentRecord));
finally
VarArrayUnlock(StudOle);
end;
// Вызываю серверную процедуру, передавая ей запись StudOle
ID := DataModule1.SocketConnection1.AppServer.Add_Student(StudOle, ErrMsg);


Сервер:

function TCcs_serv_rdm.Add_student(OleStudData: OleVariant;
out ErrMsg: WideString): Integer;
var POleStudData : pointer;
StudData : StudentRecord;
// ............................................................
begin
// Раскрываем OleStudData в StudData

POleStudData:=VarArrayLock(OleStudData);
Move(POleStudData^, StudData, SizeOf(StudData));
VarArrayUnLock(OleStudData);
try
ShowMessage(StudData.Main.FirstName); // Просто хочу вывести что-нибудь, и здесь возникает Access Violation. То же самое происходит и при любом другом подобном вызове
except
on E : Exception do ShowMessage(E.Message)
end;



Last Hero   (2002-02-20 23:04) [10]

Sorry, это я просто уже экспериментировал... Поправка, чтобы выглядело как в примере:

Сервер:

function TCcs_serv_rdm.Add_student(OleStudData: OleVariant;
out ErrMsg: WideString): Integer;
var POleStudData : pointer;
StudData : StudentRecord;
// ............................................................
begin
// Раскрываем OleStudData в StudData

POleStudData:=VarArrayLock(OleStudData);
Move(POleStudData^, StudData, SizeOf(StudentRecord));
VarArrayUnLock(OleStudData);
try
ShowMessage(StudData.Main.FirstName); // Просто хочу вывести что-нибудь, и здесь возникает Access Violation. То же самое происходит и при любом другом подобном вызове
except
on E : Exception do ShowMessage(E.Message)
end;




Digitman   (2002-02-21 09:04) [11]

а как ты думаешь, чему равно значение SizeOf(StudData.Main.FirstName) ?



Digitman   (2002-02-21 09:26) [12]

1. Посчитай, сколько всего полей в записи StudentRecord (включая поля во всех вложенных в нее записях - MainStudentRecord, LanguageRecord и т.д.). Пусть полученное тобой значение будет равно N.

2. Создай на кл.стороне массив
var
StudOle : OleVariant;
StudOle := VarArrayCreate([0, N - 1], OleVariant);

3. Заполни массив
var
StudData : StudentRecord;

with StudData do begin
StudOle[0]:= ID;
...
StudOle[1]:= Main.FirstName;
...
StudOle[N-1]:= notes;
StudOle[N-2]:= knollege;
end;

4. Передай StudOle серверу в параметре вызова Add_student(), так, как ты это и делал ранее

5. На серв.стороне создай экз-р записи
var
StudData : StudentRecord;

6. Заполни экз-р из принятого параметром массива

with StudData do begin
OleStudData[0]:= ID;
...
OleStudData[1]:= Main.FirstName;
...
OleStudData[N-1]:= notes;
OleStudData[N-2]:= knollege;
end;

Это - самый надежный и верный способ в ситуации, когда структуры данных изначально не продуманы в части потенциальной необходимости трансляции их в иное АП с использованием OLE-механизма !



Last Hero   (2002-02-21 12:16) [13]

> Digitman ©

Спасибо

Придется видимо так, жаль, не очень все таки изящное решение, вот захочется мне в какую нибудь запись новое поле добавить, и все индексы придется менять, или логическое их следование будет крайне неудачным :-(



Digitman   (2002-02-21 12:59) [14]

чтобы твое "изящное" решение с минимальными затратами/переделками адаптировать к OLE-механизму, посоветую следующее :

- откажись от WideString - этот тип в данном контексте совершенно необязателен; используй вместо него string[k], где k -максимально возможное число символов, предполагаемое в любой из строк, формирующих значения текст.полей любой из задействованных тобой структур;

- обрати особое внимание на поле MainStudentRecord.Photo -
при передаче на сервер этого поля ты можешь снова "наступить на те же грабли", если поле инициализировано как вариантная переменная, содержащая не собственно данные, а ссылку на них в АП клиента



Набережных С.   (2002-02-21 16:15) [15]

Digitman © (21.02.02 12:59) практически все сказал, добавить остается немногое.


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


Эта проблема давно решена путем передачи метаданных.

Реализация маршалинга через вариантный массив конечно проще, чем полноценная реализация IMarshal и уступает, пожалуй, только в скорости, но не стоит за это браться, не разобравшись досконально в особенностях всех типов данных.



SerVS - S   (2002-02-21 17:58) [16]

var s: string;
v: variant;

begin
...
SetLength(s, Sizeof(TYourRecord));
Move(YourRecord, s, SizeOf(TYourRecord));
v := s;
...
end;
Обратно точно также! Извини не уверен за порядок параметров в Move



Digitman   (2002-02-21 18:44) [17]

>SerVS - S
Ты о чем ?
Мы вот тут - о маршаллинге как бы)



SerVS - S   (2002-02-22 18:52) [18]

Я заметил ;), но вопрос был как преобразовать рекорд с вариант.
Если длина полей в Рекорде постоянная, то результат получите такой как просили. Если внутри есть строки, дин.массивы и т.д. то постепенно, в вопросе было "Существует очень много статей, как это сделать с массивами, картинками, бинарной информацией". Ну вот и воспользуйся этим всем последовательно ;) (одна функция для упаковки вторая для распаковки)



Набережных С.   (2002-02-22 19:45) [19]


> SerVS - S (21.02.02 17:58)


Вариант рабочий(если устранить ошибку), но неоптимальный по скорости.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.11;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.76 MB
Время: 0.017 c
1-32479           cvlexx                2002-02-20 09:52  2002.03.11  
Установка D6


14-32568          Philip                2002-01-27 00:43  2002.03.11  
Цена Delphi 6.0


3-32428           TSV                   2002-02-08 10:26  2002.03.11  
Господа, есть вопрос по Access.


14-32547          Blackweber            2002-01-15 01:24  2002.03.11  
Срочно!!!Тем кто разбирается в компах!


7-32581           Denst                 2001-11-28 21:20  2002.03.11  
Как запретить удаление и изменение конкретного файла?