![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите преобращовать Record в Variant! [D5]
Last Hero © (2002-02-19 21:38:00)Проблема. Нужно преобразовать переменную типа Record в Variant. Существует очень много статей, как это сделать с массивами, картинками, бинарной информацией, но нигде не нашел, как преобразовать Record.
Помогите!!!!!!!!
Набережных С. (2002-02-22 19:45:00) [1]
> SerVS - S (21.02.02 17:58)
Вариант рабочий(если устранить ошибку), но неоптимальный по скорости.
SerVS - S (2002-02-22 18:52:00) [2]Я заметил ;), но вопрос был как преобразовать рекорд с вариант.
Если длина полей в Рекорде постоянная, то результат получите такой как просили. Если внутри есть строки, дин.массивы и т.д. то постепенно, в вопросе было "Существует очень много статей, как это сделать с массивами, картинками, бинарной информацией". Ну вот и воспользуйся этим всем последовательно ;) (одна функция для упаковки вторая для распаковки)
Digitman (2002-02-21 18:44:00) [3]>SerVS - S
Ты о чем ?
Мы вот тут - о маршаллинге как бы)
SerVS - S (2002-02-21 17:58:00) [4]var s: string;
v: variant;
begin
...
SetLength(s, Sizeof(TYourRecord));
Move(YourRecord, s, SizeOf(TYourRecord));
v := s;
...
end;
Обратно точно также! Извини не уверен за порядок параметров в Move
Набережных С. (2002-02-21 16:15:00) [5]Digitman © (21.02.02 12:59) практически все сказал, добавить остается немногое.
> вот захочется мне в какую нибудь запись новое поле добавить,
> и все индексы придется менять, или логическое их следование
> будет крайне неудачным
Эта проблема давно решена путем передачи метаданных.
Реализация маршалинга через вариантный массив конечно проще, чем полноценная реализация IMarshal и уступает, пожалуй, только в скорости, но не стоит за это браться, не разобравшись досконально в особенностях всех типов данных.
Digitman (2002-02-21 12:59:00) [6]чтобы твое "изящное" решение с минимальными затратами/переделками адаптировать к OLE-механизму, посоветую следующее :
- откажись от WideString - этот тип в данном контексте совершенно необязателен; используй вместо него string[k], где k -максимально возможное число символов, предполагаемое в любой из строк, формирующих значения текст.полей любой из задействованных тобой структур;
- обрати особое внимание на поле MainStudentRecord.Photo -
при передаче на сервер этого поля ты можешь снова "наступить на те же грабли", если поле инициализировано как вариантная переменная, содержащая не собственно данные, а ссылку на них в АП клиента
Last Hero (2002-02-21 12:16:00) [7]> Digitman ©
Спасибо
Придется видимо так, жаль, не очень все таки изящное решение, вот захочется мне в какую нибудь запись новое поле добавить, и все индексы придется менять, или логическое их следование будет крайне неудачным :-(
Digitman (2002-02-21 09:26:00) [8]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-механизма !
Digitman (2002-02-21 09:04:00) [9]а как ты думаешь, чему равно значение SizeOf(StudData.Main.FirstName) ?
Last Hero (2002-02-20 23:04:00) [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;
Last Hero (2002-02-20 23:00:00) [11]Запись (в 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;
Набережных С. (2002-02-20 21:32:00) [12]Покажи код
Last Hero (2002-02-20 20:24:00) [13]Сделал все так, как в примере...
Я таким образом пытаюсь передать данные на сервер приложений (MIDAS)...
Все нормально компилится, как будто работает (то есть в данных в примере строчках кода никаких exception нет), но при попытке обращения на сервере к любому из полей рекорда появляется Access Violation :-(
Как это может быть?
Набережных С. (2002-02-20 16:21:00) [14]Посмотри
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=9090
Last Hero (2002-02-20 13:57:00) [15]>SEM © and Юрий Федоров ©
Именно это я и имел в виду, пожалуйста, приведите пример, как это можно сделать?
Юрий Федоров (2002-02-20 11:04:00) [16]И для копирования использовать VarArrayLock, VarArrayUnLock
SEM (2002-02-20 10:39:00) [17]Может я не понял вопроса, но может быть спасет
функция VarArrayCreate, с помощью которой можно создать
массив байтов примерно так:
V: Variant;
...
V := VarArrayCreate([...], varByte);
И копирнуть туда record.
Digitman (2002-02-20 08:51:00) [18]никак. переменные вариантного типа не поддерживают автоматическое управление распределением памяти под пользовательские типы данных
Last Hero (2002-02-20 08:26:00) [19]Ответьте!!! Please...
Как можно преобразовать Record в Variant Array? И можно ли? А также обратно преобразовать в Record... И, пожалуйста, просто пример кода!!!