Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 26.02.2012, 00:45
Sahan911 Sahan911 вне форума
Прохожий
 
Регистрация: 08.08.2011
Адрес: Воронеж
Сообщения: 14
Версия Delphi: 2006,7,10
Репутация: 10
Сообщение Передача типа как параметр

Всем доброго времени суток! Понадобилась помощь. Все перерыл, не знаю как передавать тип, как параметр, как это делает к примеру функция SizeOf. Мы в параметр фенкции передаем тип например Integer, а она в свою очередь возврашает нам размер типа. Я хочу также передавать тип как параметр, а еще использовать переменные типа тип. Чтобы вопрос был понятен вот пример, как я хотел бы чтобы выглядел мой код:
Код:
Var
  VarType: AnyType;
...

Procedure MyProc(MyType: AnyType);
Var Buff: Pointer;
begin
...
  GetMem(Buff, SizeOf(MyType));
...
  FreeMem(Buff);
...
end;

...

begin
 MyProc(Integer);
end.

Заранее благодарен за помощь!

Последний раз редактировалось Sahan911, 26.02.2012 в 21:11.
Ответить с цитированием
  #2  
Старый 26.02.2012, 01:10
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Насколько я знаю, SizeOf - не функция, а "магический" макрос. Проще передавать количество байт, занимаемых типом для приведенного выше кода.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
Sahan911 (26.02.2012)
  #3  
Старый 26.02.2012, 21:06
Sahan911 Sahan911 вне форума
Прохожий
 
Регистрация: 08.08.2011
Адрес: Воронеж
Сообщения: 14
Версия Delphi: 2006,7,10
Репутация: 10
Восклицание Re: Передача типа как параметр

Ну Макрос - это таже самая функция, только она описана где - то в Dll. Впринципе для данной ситуации можно передавать количество байт, но это не совсем то что мне нужно. Это лишь был пример как я могу использовать этот параметр. А если я захочу вот такую ситуацию сделать?:
Код:
Procedure MyProc(Param: AnyType);
Var MyVar: AnyType;
Ptr: Pointer;
Int: Integer;
begin
...
GetMem(Ptr, SizeOf(Param));

...
MyVar := FuncЧтоЗаТип(Int);
Int := MyVar(Ptr^);


end;

Т. Е. я хочу иметь переменую типа ТИП, или что - либо в этом духе, например чтобы определить размер с помощью функции SizeOf или для типизации разыменованного нетипизированного указателя. Если это возможно, то я еще хочу знать есть ли такая функция (FuncЧтоЗаТип), которая возвращает тип переменной. Если это не возможно есть ли методы , благодаря которым можно реализовать нечто подобное? Еще раз заранее спасибо.
__________________
Код:
ShowMessage('HelloWorld!');
Ответить с цитированием
  #4  
Старый 26.02.2012, 21:29
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

У вас в корне не верное представление о макросе. Макрос - это значит, что код записывается на его месте. Никаких вызовов функции там нет. То есть на месте SizeOf(Integer) подставится 4 еще при компиляции. DLL тут ни при чем.
А вот описанная задача решается далеко не просто. Любые компиляторы, позволяющие использовать такое (например, технология шаблонов в C++) делают несколько вариантов функции для каждого случая. Опишу подробнее.
Когда вы пишете
Код:
procedure a123(...);
var a:AnyType;
локальная переменная "a" будет создаваться в стеке программы. То есть в начале в стеке будет пропущено некоторое количество байт (для Integer 4, для Byte 1). Это делается на ассемблере так:
Код:
sub esp, 4 ; Вычитаем из текущего адреса в стеке 4 байта. Теперь есть "зарезервированное" место,
               ; которое можно использовать для своих нужд; к нему никто не обратится.
И такой код генерируется в начале процедуры.
А если там неизвестный тип, то что ему вычитать? 1, 2, 4, 8, 10000? Это еще решаемо, но: а как потом с ним работать? Для сложения двух байт будет один код, а для двух строк - совершенно другой, ни капли не похожий.
Примерно так:
Код:
; сложить байтовые переменные a и b, aka a:=a+b
 mov al, [b]              ; значение одного байта
 add [a], al               ; прибавить к другому байту

; сложить строки aka Str1:=Str1+Str2
 mov eax, [Str2]        
 push eax                 ; адрес второй строки
 mov eax, [Str1]        
 push eax                 ; адрес первой строки
 push eax                 ; адрес результирующей строки
 call StrAdd              ; довольно длинная функция, дописывающая одну строку в конец другой.
Пришли к выводу, что скомпилировать "универсальный" код невозможно (без капитальной потери производительности).
Делфи же является компилируемым языком, т.е. работающем непосредственно на железе. В скриптовых такая задача решается довольно просто: интерпретатор (программа, выполняющая код скрипта) может содержать в себе код работы с любыми типами, перед сложением проверить, какого типа переменные, и выбрать соответствующую функцию сложения.
В компилируемых языках такая задача частично решается при помощи ООП и перегрузки операторов, однако это совсем другая история (и, кстати, достаточно медленная: если для сложения двух байт вызывать функцию - будут потери производительности раз в 5-10).

Реализовать "нечто подобное" можно, например так: в функцию передаем ID типа (придумываем его сами: Byte-1, Word-2, Integer-3,...) и выбираем код в зависимости от переданного параметра обычным If или Case.
Хотя честно говоря, уж не знаю, зачем такое может понадобится. Мне такое не нужно было ни разу в жизни. Вполне возможно, что есть более простые и быстрые решения вашей задачи.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 26.02.2012 в 21:55.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
Sahan911 (26.02.2012)
  #5  
Старый 26.02.2012, 23:14
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,030
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Вообще, данная задача решается либо через generics/templates (если не ошибаюсь, то начиная с Delphi 2010 или XE они уже есть), либо через классы. Фактисески, тебе надо описать некоторый класс, имеющий некоторое стандартное поведение. Тогда любой другой твой тип будет наследником этого класса со всеми вытекающими...

Например, есть у нас базовый класс и функция, его использующая:
Код:
type
  TMyTypeBaseClass = class
  private
    FMem : Pointer;
  public
    procedure ClassGetMem; virtual; abstract;
    procedure ClassFreeMem; virtual; abstract;
    procedure DoWork; virtual; abstract;

    property ClassMem : Pointer read FMem;
  end;

procedure MyProc(MyVar : TMyTypeBaseClass);
begin
  MyVar.ClassGetMem;
  MuVar.DoWork;
  MyVar.ClassFreeMem;
end;

Теперь можно создавать наследников этого класса и передавать из в эту процедуру.

PS. На самом деле, когда ты используешь темплейты или дженерики, то компилятор в момент компиляции просто инстанциирует данный шаблон для переданного типа. Т.е. если у нас есть:
Код:
var
  L1 : TList<Integer>;
  L2 : TList<String>;

(не помню как там дженерики пишутся, т.к. пользуюсь пока Delphi 7, где их нет), то в скомпилированном коде по факту будет 2 экземпляра класса TList - один для целых и один для строк. Причем будет и 2 экземпляра кода. И это не только в Дельфи, в C++ и C# тоже самое происходит (в Java не уверен, т.к. эта штука может классы создавать на лету, бо как работает на виртуальной машине).

Последний раз редактировалось lmikle, 26.02.2012 в 23:19.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Sahan911 (26.02.2012)
  #6  
Старый 27.02.2012, 00:01
Sahan911 Sahan911 вне форума
Прохожий
 
Регистрация: 08.08.2011
Адрес: Воронеж
Сообщения: 14
Версия Delphi: 2006,7,10
Репутация: 10
По умолчанию

lmikle, Все верно, но мне нужно передавать не объекты, как параметр, а тип как параметр. Или например создать переменную типа ТИП. т.е.
Код:
Var MyType: AnyType; 
...
begin
MyType:= integer;
...
MyType := String; //и т.д. и т.п.

Объекты передавать легко, а определять тип я не знаю как. Скорее всего это невозможно или очень сложно, но я всеже надеюсь получить ответ.
__________________
Код:
ShowMessage('HelloWorld!');
Ответить с цитированием
  #7  
Старый 27.02.2012, 00:05
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Как можно передать тип, если тип - это понятие, существующее только на этапе компиляции программы? Это просто несколько букв, в зависимости от которых комиплятор ведёт себя по-разному. После компиляции никаких типов не существует, существуют байты и их количество.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
Sahan911 (27.02.2012)
  #8  
Старый 27.02.2012, 00:11
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,030
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Ну, тут можно посмотреть в сторону метаклассов. Экземпляр метакласса собственно и есть класс, т.е. тип. Но все-равно не понимаю зачем оно тебе. Я тебе дал пример нормального решения для твоей задачи. Более того, это даже можно использовать из bpl-ей (из dll нельзя, т.к. там TObject'ы будут разные, но можно и попробовать - если не надо проверять тип, а пользоваться только интерфейсом класса, то должно прокатить).

А вообще, что тебе мешает использовать вариант (Variant). Посмотри функции работы с вариантами... там ест и получение типа варианта.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Sahan911 (27.02.2012)
  #9  
Старый 27.02.2012, 00:19
Sahan911 Sahan911 вне форума
Прохожий
 
Регистрация: 08.08.2011
Адрес: Воронеж
Сообщения: 14
Версия Delphi: 2006,7,10
Репутация: 10
По умолчанию

Сорри , (конечно с этого надо было начинатть) я забыл сказать, что данную задачу я решаю сейчас не в Delphi а в ABC Pascal . Там немного все по - другому и нет типа Variant(я с ним в Delphi работал).
__________________
Код:
ShowMessage('HelloWorld!');
Ответить с цитированием
  #10  
Старый 27.02.2012, 05:56
Pyro Pyro вне форума
Так проходящий
 
Регистрация: 18.07.2011
Сообщения: 805
Версия Delphi: 7Lite
Репутация: 6063
По умолчанию

PHP код:
не совсем то что мне нужно 
PHP код:
реализовать нечто подобное 
PHP код:
Там немного все по другому 
PHP код:
Объекты передавать легко 

военная тайна что-ли?
зачем это передавать то?
что это должно дать?
и что из этого не дают объекты?
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 18:08.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter