Показать сообщение отдельно
  #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.
Ответить с цитированием