Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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)


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



Страницы: 1 вся ветка

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

Наверх





Память: 0.49 MB
Время: 0.004 c
1-32478
Geser
2002-02-23 21:16
2002.03.11
RxLib und D6


4-32609
ЛамерОК
2002-01-10 23:29
2002.03.11
Раскладка клавиатуры!


4-32606
Death
2002-01-11 04:30
2002.03.11
Плиз, хелп :)


4-32612
Landgraph
2002-01-11 11:57
2002.03.11
С OpenGL никто не обсчался чтоли?!


14-32565
Dimitry_I
2002-01-28 14:50
2002.03.11
Помогите, очень прошу





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский