У вас в корне не верное представление о макросе. Макрос - это значит, что код записывается на его месте. Никаких вызовов функции там нет. То есть на месте 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.
Хотя честно говоря, уж не знаю, зачем такое может понадобится. Мне такое не нужно было ни разу в жизни. Вполне возможно, что есть более простые и быстрые решения вашей задачи.