Magic Pointers («красивые» указатели на функции, вызов)

Обсуждение проектов наших жителей.
Вы можете выставить проект на тест или найти помощников для его реализации.

Модератор: BV

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 28.02.2011 (Пн) 21:31

.
.
Предисловие
Для тех, кому лень или некогда много читать, основные тезисы:
  • Я сделал модуль, который вносит в VB поддержку указателей на функции и вызова функций через эти указатели.
  • Модуль поддерживает VB6, VB5, компиляцию в Native-код, компиляцию в P-код и работу под IDE без каких-либо ограничений, не нуждается в дополнительных библиотеках, в установке Add-in'ов для VB, не использует ассемблерных вставок и тому подобного. В VBA (в Office) тоже должен сработать.
  • Модуль оформлен как «кирпич». Хотите скачать модуль — идите по этой ссылке.
  • В той теме — сухое описание, самая последняя версия, обсуждения строго по теме, сообщения об обнаруженных багах.
  • В этой теме — обсуждение самой идеи, рассуждения на тему, впечатления, мнения.


Вступление
Что такое указатель на функцию?
Физически — это ячейка памяти, в которой хранится адрес какой-то функции.
Семантически — это особая переменная, используя которую можно сделать вызов любой нужной функции. Кроме того, с такой переменной связана контрольная информация о функции: количество и тип всех её параметров и тип возврата. Так что язык/средство разработки проконтролирует, чтобы функцию вызывали всегда именно так, как она сама того ожидает.

Так уж сложилось, что (из соображений безопасности) в VB указателей на функции (во втором смысле) нет.
Вот в Си, например, указатели на функцию есть:
Код: Выделить всё
int (*func_ptr_1)(char a, long b); // Мы объявили указатель на функцию, принимающую 2 параметра и возвращающую int
...
x = func_ptr_1(4, 5); // Мы вызвали функцию по указателю на неё


Си не даст нам вызвать функцию по указателю, передав три параметра вместо двух или один. Си проконтролирует правильность типов. Задача была сделать в VB6 что-то такое же лёгкое в использовании и синтаксически дружественное.

Замысел
Дело в том, что в VB нет указателей на функции именно во втором смысле. В первом смысле указатели на функции для вызова каких-то функций используются в трёх случаях:
  • Для вызова методов классов при раннем связывании.
  • Для вызова модульных процедур, объявленных в TLB, располагающихся сторонних библиотеках.
  • Для вызова процедур, объявленных через Declare Sub/Function.

Привязаться к первому нельзя: имеет место быть неявная передача первым параметром ссылки на Me (This).
Привязаться ко второму нельзя: адреса импортируемых функций кешируются в регистрах, так что перезапись IAT не даст эффект сразу же.
А вот к третьему... Никаких преград.

Вы объявляете:
Код: Выделить всё
Declare Sub Foo Lib "xxx" ()


И со стандартной точки зрения — это объявление процедуры Foo из библиотеки xxx, а мы сделаем так, что при особом (волшебном!) значении Lib это будет считаться не функцией из библиотеки, а переменной-указателем. И можно будет присвоить переменной-указателю Foo любое значение и сделать вызов.

Набросочно, так:
Код: Выделить всё
Foo = 123123
Foo()
Foo = 7798987
Foo()


Немного истории
  • Впервые эта идея пришла мне в голову, судя по всему, 06 ноября 2008 года — вот здесь (там же она была впервые описана). Был начат писаться модуль, было написано некоторое количество кода, а затем это дело было заброшено.
  • Второй раз об идее я вспомнил и более подробно написал о ней чуть больше года назад — в начале февраля 2010. Тогда же был дописан модуль, вызовы по указателям работали, но только в скомпилированном файле. На тот момент решения проблемы, не дающей использовать указатели в IDE, приемлемого я не видел. Модуль был заброшен ещё на год. Если прочитать ту тему полностью, можно найти уже там много подробностей, которые будут далее изложены здесь. :wink:
  • Недавно я вспомнил о своей давней задумке и стал писать модуль — с нуля. И в процессе понял, что забыл многие аспекты внутреннего устройства «момента». Но вспомнил, что где-то на форуме я вдавался в какие-то подробности, и стал искать их. И наткнулся на код, который по стилю был похож на мой собственный, но при этом я абсолютно не помнил о том, что писал такой код. Как оказалось, модуль, который я честно собирался написать с нуля, уже был на 90 процентов написан, а я об его существовании просто забыл. :)

Техника
VB(A) устроен так:
Для всех существующих в проекте Declare-функций имеется одна таблица, в которой хранятся адреса вызываемых функций. Это можно назвать таблицей отложенного импорта, но эта таблица отложенного импорта не имеет ничего общего с той таблицей отложенного импорта, которую определяет PE-формат. Это VB-специфичная таблица, и для каждой Declare-функции имеется ячейка, которая хранит адрес соответствующей Declare-функции.

Изначально эта таблица вся заполнена нулями.

Как только какая-либо из Declare-функций вызывается в первый раз, в её ячейке содержится 0, что означает, что адрес функции ещё не известен. При этом (в первый раз) вызывается DllFunctionCall.

DllFunctionCall определяет адрес вызываемой сейчас функции и заносит его в таблицу.

DllFunctionCall (несмотря на название) не вызывает функцию. На самом деле её название не CallDllFunction (вызвать Dll-функцию), а DllFunctionCall (вызов Dll-функции). То есть она просто обрабатывает вызов, причём только самый первый.
Последующие вызовы некоторой Declare-функции берут адрес прямо из таблицы и делают переход по нему. Никакие посторонние функции, кроме самой вызываемой функции, не вызываются. Вызов получается достаточно быстрым.

Алгоритм действия при вызовах Declare-функций следующий:
Изображение

Здесь нужно сделать два важных вывода:
  • Перехватывая вызов DllFunctionCall, можно полностью контролировать процесс преобразования пар {функция;библиотека} в адреса. Например, можно пакостить: когда программист вызывает MessageBox из user32, возвращать адрес ExitProcess из kernel32. :) То есть мы имеем возможность сделать так, чтобы вместо той функции, которую вызывают, выполнилась любая, какая нам хочется.
  • Для каждой Declare-функции существует физическая переменная-указатель, хранящая адрес, по которому совершается вызов. Теоретически можно править этот адрес, и вызовы, совершённые после правки, пойдут по новому адресу. Но мы не имеем хорошего интерфейса доступа к этой переменной, не можем напрямую читать и писать в неё нужное нам значение-адрес.

И вывести следствия:
  • Итак, раз DllFunctionCall занимается выяснением адреса функции по имени библиотеки и имени/ординалу функции, совершенно очевидно, что ей (DllFunctionCall) передаётся эта информация (имя библиотеки, имя/ординал функции).
  • DllFunctionCall также записывает в таблицу вместо нуля адрес найденной функции. Значит она не только знает имя функции, которую сейчас вызывают, но и знает, где расположена ячейка таблицы (она же физическая переменная-указатель) для данной функции.

А значит, для нужных нам Declare-функций мы можем как «подставить» какой-то свой произвольный адрес, подменив DllFunctionCall на свою функцию функцию-аналог, так и узнать, где располагаются ячейки, хранящие адреса, для нужных нам функций. А узнав местоположение ячеек, мы фактически владеем настоящими указателями на функции: синтаксический контроль есть, возможность менять значени указателя есть, возможность делать вызов по этому адресу — есть.

Остаётся только отделить Declare-функции, используемые как указатели на функции, от Declare-функций, используемых по прямому назначению.

Сделать это довольно легко: достаточно для Declare-функций, играющих роль указателей, в качестве библиотеки указывать такую строчку, которая заведомо не может являться именем файла библиотеки.

Например:
Код: Выделить всё
Declare Sub Example1 Lib ":::" ()
Declare Sub Example2 Lib "***" ()
Declare Sub Example3 Lib "???" ()

Совершенно точно, что в имени файла библиотеки этих символов быть не может. Значит мы имеем возможность принять особое волшебное значение «параметра» Lib, которое бы говорило нашему заменителю DllFunctionCall, что это не Declare-функция в истинном виде, а наш волшебный указатель, и обрабатывать его нужно по-особенному, а не отдавать дело в руки оригинальной DllFunctionCall.

Я в качестве волшебного признака (имя библиотеки) взял одинарную звёздочку — просто и со вкусом.

Вот так выглядит алгоритм действий при первом вызове Declare-функций после включения волшебных указателей:
Изображение

Предположим, у нас есть следующая Declare-функция:
Код: Выделить всё
Declare Function MagicPointer1 Lib "*" (ByVal x As Long, ByRef Y as string) as Integer


И совершается вызов функции. Поскольку это первый вызов, ячейка таблицы адресов содержит ноль. Раньше выполнение перешло сразу в DllFunctionCall, но теперь оно переходит в нашу функцию-перехватчик. Наша функция перехватчик получается всю необходимую информацию: в частности, что вызываемая функция имеет имя «MagicPointer1», а имя библиотеки — «*». Наша функция-перехватчик понимает, что библиотеки с таким именем быть не может, что это специальный маркер, и делает следующее: пытается в своём массиве (коллекции, словаре) найти адрес, соответствующий указателю с именем «MagicPointer1». Если это удаётся, этот адрес записывается в таблицу адресов и возвращается. Вызов идёт по этому адресу. Все довольны.

Что будет, когда будет сделан второй (третий, четвёртый, и так далее) вызов MagicPointer1? В этот раз в ячейке не будет нуля. В ячейке будет адрес, поставленный туда в прошлый раз нашей функцией-перехватчиком. И именно по этому адресу сразу же устремится выполнение.

Но что, если нам нужно поменять значение нашего указателя? Ведь перехватчик никогда больше не будет вызван (потому что в таблице в ячейке не ноль), а значит у него не будет шанса заменить теперь уже старое значение в таблице на новое значение указателя?

Решается это очень просто: из тех соображений, что перехватчик больше не будет вызын для этой функции, он добавляет в другой свой массив (коллекцию, словарь) имя переменной-указателя и сопоставляет ему адрес ячейки таблицы адресов. Теперь, когда нам нужно изменить значение указателя MagicPointer1, мы знаем, куда напрямую нужно писать новый адрес.

Поэтому я делаю все указатели на две группы:
  • Undiscovered — те, для которых первого вызова ещё не состоялось, а значит адрес ячейки с адресом для данного указателя ещё не известен. Для этих указателей хранится сопоставление ИмяУказателя --> ЗначениеУказателя.
  • Discovered — те, для которых первый вызов уже состоялся, и поэтому адрес ячейки таблицы адресов известен. Для этих указателей не хранятся их значения, а хранятся адреса соответствующих ячеек таблицы адресов, в которых наконец и хранятся сами значения этих указателей.

Как только происходит самый первый вызов какого-либо очередного указателя, если функция-перехватчик находит имя текущего указателя в наборе Undiscovered, она переносит этот указатель в набор Discovered. В противном случае генерируется ошибка: «Specified pointer is not set.», которую программист может отработать. Если же функция-перехватчик вызывается, а текущий указатель уже находится в категории Discovered, значит указатель был обнулён после первичного вызова. В этом случае генерируется ошибка «Null pointer call». Именно так: мой модуль вынужденно не даёт вам «выстрелить себе в ногу», вызвав код по адресу 0.

Отключение же магических указателей ещё более простое: нужно снять перехват функции DllFunctionCall, пройтись по набору Discovered-указателей и занулить их ячейки таблицы адресов. Тогда последующие обращения к ним пойдут в стандартную DllFunctionCall, которая честно заявит: «File not found: *».

Технические проблемы
Методика порождения указателей на функции одинакова как для скомпилированных файлов, так и для проекта, работающего под IDE. Поэтому включение и выключение указателей на функции выполняется одинаково — перехватом DllFunctionCall.

Однако в отличие от скомпилированного файла, перехват DllFunctionCall в среде разработке (IDE) оказывается достаточно сложной задачей. В скомпилированном файле для модуле-локального перехвата DllFunctionCall достаточно заменить значение ячейки IAT этого самого модуля. Все обращения к DllFunctionCall из этого модуля пойдут по новому направлению, а вызовы из других модулей останутся незатронутыми. В случае работы проекта под IDE, никакой IAT с ячейкой, которую можно было бы перезаписать, просто нет. При работе под IDE используется DllFunctionCall из vbaX.dll. Эта функция экспортируется, но вызов DllFunctionCall идёт из самой vbaX.dll, так что это внутримодульный вызов. Для каждой Declare-функции по одному шаблону создаётся свой динамически генерируемый кусочек Native-кода, в который адрес DllFunctionCall прошит жесткой константой. Так что единственной возможностью проект-локального перехвата DllFunctionCall является поиск всех динамически сгенерированных кусочков кода и перезапись адреса DllFunctionCall прямо в этих кусочках на свой адрес. Для этого используются функции из vbaX.dll, с помощью которых можно получить множество информации и загруженных в IDE проектах. В том числе и адреса динамически сгенерированных кусочков-переходничков для Declare-функций.

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

Итоги
  • Мы имеем модуль, превращающий Declare-функции в функции-указатели со множеством достоинств.
  • Указатели на функции требуют указания прототипа вызываемой функции, что повышает контроль за правильностью кода.
  • Модуль генерирует ошибки при попытках использования Null-указателя, а не допускает Access violation.
  • У каждого проекта своё изолированное пространство указателей. Одноимённые указатели в двух (и более) одновременно работающих (в рамках одного процесса) VB-проектах не мешают друг другу и никак не влияют друг на друга.
  • Модуль работает как в VB6, так и в VB5, и должен заработать в VBA-приложениях (пока не проверялось за неимением оных).
  • Модуль автономен: не нужны доп. библиотеки, не нужна модификация среды, нет пугающих многих ассемблерных вставок.
  • В отличие от многих подобных трюков: работает без малейших ограничений в IDE и в файлах, скомпилированных в псевдокод.
  • Вызов (не первый) по такому указателю очень быстр: единственный накладной ресурс, по сравнению с вызовом по указателю, например, в Си — проверка указателя на равенство нулю.
  • Не выключенная поддержка указатель не фатальна (как, например, неснятый сабклассинг).
  • Возможно объявить множество различных прототипов для одного указателя:
    Код: Выделить всё
    Declare Function FooAsAny Lib "*" Alias "Foo" (x as any) as long
    Declare Function FooAsLong lib "*" Alias "Foo" (ByVal x As Long) As Long
    Declare Function FooWithoutParams Lib "*" Alias "Foo" () As Long ' Даже так
  • Указатели могут быть объявлены как публичные и как приватные. В модулях, в классах, формах — где угодно, так же, как это действует для простого Declare.

Недостатки:
  • Свойственная Declare конвертация Unicode->Asciiz и обратно. Легко борется As Long или As Any параметрами.

Благодарности
  • iGrok-у — за удалённую отладку модуля на VB5 (которого у меня нет) и моральную поддержку,
  • arthur2 — за напоминание год назад о забытом три года назад модуле :)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение BV » 01.03.2011 (Вт) 11:37

Умеешь ты достаточно простую работу описать, как глубокое и высшей степени сложное исследование, да..
У меня по ходу прочтения возник вопрос: а что же ты не использовал сплайсинг для перехвата DllFunctionCall?
Кроме того, ты забыл указать на другой недостаток, необходимость работы с таблицей через FuncPointer для инициализации указателей, вместо более дружелюбного присваивания указателя непосредственно функции
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 01.03.2011 (Вт) 11:41

BV писал(а):У меня по ходу прочтения возник вопрос: а что же ты не использовал сплайсинг для перехвата DllFunctionCall?

Это же очевидно: DllFunctionCall — одна, а проектов (у каждого из которых своё пространство указателей и своя LocalResolver) — много. Плюс неснятый перехват в этом случае окажется фатальным. Плюс ассемблерный вставки, которые всех пугают.

Кроме того, ты забыл указать на другой недостаток, необходимость работы с таблицей через FuncPointer для инициализации указателей, вместо более дружелюбного присваивания указателя непосредственно функции

Ты же понимаешь, что тут уже пришлось бы писать Add-in, потому что это синтаксически противоестественно для VB.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение BV » 01.03.2011 (Вт) 11:57

Хакер писал(а):Это же очевидно: DllFunctionCall — одна, а проектов (у каждого из которых своё пространство указателей и своя LocalResolver) — много.

В обработчике можно следить за именем проекта, или найти другой способ дифференциации
Хакер писал(а):Ты же понимаешь, что тут уже пришлось бы писать Add-in, потому что это синтаксически противоестественно для VB.

Понимаю. И я бы так и сделал, написал add-in, обрабатывающий строку вида
Код: Выделить всё
'_funcname_ = ptr
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 01.03.2011 (Вт) 12:13

BV писал(а):В обработчике можно следить за именем проекта, или найти другой способ дифференциации

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

Понимаю. И я бы так и сделал, написал add-in, обрабатывающий строку вида

Тогда бы я не смог написать этой строчки:
Модуль поддерживает VB6, VB5, компиляцию в Native-код, компиляцию в P-код и работу под IDE без каких-либо ограничений, не нуждается в дополнительных библиотеках, в установке Add-in'ов для VB, не использует ассемблерных вставок и тому подобного. В VBA (в Office) тоже должен сработать.

Никто не любит Add-in-ы, такие, что без них проект не скомпилируется. Я когда предлагал людям при обсуждении деталей заказа, что в проекте будет применен FNDLL, их не устривало, что в дальнейшем людям, которые будут поддерживать проект, надо будет ещё какой-то сторонний софт доустанавливать.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение BV » 01.03.2011 (Вт) 12:33

Хакер писал(а):В чём смысл извращаться, если есть хороший надёжный способ?

Смысл в том, что не пришлось бы вылавливать динамически создаваемые вызовы в IDE.
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 01.03.2011 (Вт) 12:35

BV писал(а):Смысл в том, что не пришлось бы вылавливать динамически создаваемые вызовы в IDE.

Пришлось бы делать куда более жесткие недокументированные вещи. Но это не так страшно, как то, что реализация, попадающая в скомпилированный файл (а именно на неё надо равняться и обращать внимание), была бы на порядок сложнее и ненадёжнее, чем та, что сейчас.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 01.03.2011 (Вт) 13:17

Здорово! просто офигительно!
BV писал(а):Умеешь ты достаточно простую работу описать, как глубокое и высшей степени сложное исследование, да
Ни фига себе "простую"... По-моему, так как раз "глубокое" и "сложное". Мало того - никто до этого раньше Хакера не додумался. К тому же, ещё и очень изящно.

И уж точно, куда изящнее, и удобнее, чем '_funcname_ = ptr
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 01.03.2011 (Вт) 14:50

arthur2 писал(а):И уж точно, куда изящнее, и удобнее, чем '_funcname_ = ptr

Если уж хочется, можно сделать вместо
FuncPointer("foo") = 123
так:
fp!foo = 123, но это потребует 1 модуль класса, потому что ! применим только к ссылкам.

Что касается развития проекта:

Предполагается сделать ещё такие изменения
  • Сейчас для преобразования имя->адрес используются VB-шные коллекции. Я их выбрал, чтобы не пугать никого дополнительным кодом, потраченным на реализацию быстрых ассоциативных массивов. Коллекции в данной роли — мягко говоря, не эффективно. Можно сделать так, чтобы модуль работал по константе условной компиляции с другим модулем — «Быстрый словарь».
  • Добавить поддержку не только именованных указателей, но и нумернованных. Избавляет от преобразования имя->адрес. В роли номеров, понятное дело, используются ординалы.
  • Сделать альтернативный вариант модуля: требующий подключения в References специальной TLB (с описаниями функций и интерфейсов ITypeLib, ITypeInfo). Должно сократить количество кода, повысить его понятность.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 01.03.2011 (Вт) 16:42

Хакер писал(а):чтобы не пугать никого дополнительным кодом, потраченным на реализацию быстрых ассоциативных массивов.
Кстати, было бы интересно посмотреть на твою реализацию ассоциативных массивов :)

Что такое ординалы? :oops:
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 01.03.2011 (Вт) 16:44

arthur2 писал(а):Что такое ординалы?

:shock:

Функция может экспортироваться (а значит и импортироваться) как по имени (строчке), так и по ординалу (16-битному числу).
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 01.03.2011 (Вт) 17:07

а, вспомнил :)
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 02.03.2011 (Ср) 21:24

И никто ничего не пишет. Никому, кроме Артура, не интересно что-ли?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение SLIM » 02.03.2011 (Ср) 22:53

Хакер писал(а):И никто ничего не пишет. Никому, кроме Артура, не интересно что-ли?

Не думаю что мое мнение интересно :))
Пишите жизнь на чистовик.....переписать не удастся.....

1Steps
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 505
Зарегистрирован: 20.12.2006 (Ср) 0:50
Откуда: New York

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение 1Steps » 03.03.2011 (Чт) 4:39

Трижды заходил в эту тему(в течении окло 5 мин.). Трижды мне показывало, что новое(последнее) сообщение от proxy. Трижды я его не увидел.
Удалена за ненадобностью.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 03.03.2011 (Чт) 5:27

Хакер писал(а):И никто ничего не пишет. Никому, кроме Артура, не интересно что-ли?
Да уж... Ещё пару лет назад эта тема была бы бомбой! Обидно... Форум редеет?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 03.03.2011 (Чт) 6:11

1Steps писал(а):Трижды заходил в эту тему(в течении окло 5 мин.). Трижды мне показывало, что новое(последнее) сообщение от proxy. Трижды я его не увидел.

Потому что таблица сообщений прострадала. А таблица тем, где записано, чьим был последний пост — нет.

SLIM писал(а):Не думаю что мое мнение интересно :))

Интересно.

Proxy писал, что его интерес к VB6 угас.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Antonariy » 03.03.2011 (Чт) 11:56

Хакер писал(а):И никто ничего не пишет. Никому, кроме Артура, не интересно что-ли?
Да уж... Ещё пару лет назад эта тема была бы бомбой![/quote]Лет 10, я бы сказал.
arthur2 писал(а):Обидно... Форум редеет?
VB6 теряет актуальность.

Для какой прикладной задачи был бы полезен этот модуль?
Лучший способ понять что-то самому — объяснить это другому.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение BV » 03.03.2011 (Чт) 13:14

arthur2 писал(а):Ни фига себе "простую"...

Все зависит от уровня знаний, артур.
Но объективно, в этой задаче нет ничего сложного.

arthur2 писал(а):Да уж... Ещё пару лет назад эта тема была бы бомбой! Обидно... Форум редеет?

Да просто кому сейчас это надо? Думаю, единственный, кто извлек пользу с этой работы, это Хакер. Прибавилось опыта в реверсинжиниринге.
Остальным комфортно на .net'е и C++. Самым оригинальным еще и на Дельфи (привет, Твистер)
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 03.03.2011 (Чт) 18:25

Antonariy писал(а):Лет 10, я бы сказал
Ну, десять лет назад бомба была бы помощнее... Но и два года назад - по моим ощущениям - срезонировало бы очень даже.

BV писал(а):Но объективно, в этой задаче нет ничего сложного.
Это не в задаче, это в решении нет ничего сложного.
Очень часто чем проще, изящней и очевиднее решение, тем сложнее было его найти. Самое грандиозное техническое решение в истории - это колесо. Казалось бы - совершенно очевидная конструкция, но в Америке до Кортеса колеса не знали. Вот и до Хакера это такое "простое" решение ни кому в голову не приходило.
BV писал(а):Да просто кому сейчас это надо?
То-то и обидно, что хороший язык и хорошую технологию преждевременно хоронят.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 04.03.2011 (Пт) 4:08

Antonariy писал(а):Для какой прикладной задачи был бы полезен этот модуль?

  1. Плагины (хост на VB, плагины — на чём угодно (тоже на VB с FNDLL)).
  2. Вызов ассемблерных вставок, но не через мерзкий CallWindowProc, а красиво.
  3. Процедуры-Callback-и (как EnumЧтонибудь).
  4. Конечные автоматы, очень быстрые парсеры и тому подобное.
  5. Вызов методов объектов классов, не поддерживающих IDispatch, и для которых нет TLB, и для которых проще её не делать. В самом же модуле (эдакий BootStrap) этим методом вызывает ITypeInfo::AddressOfMethod, хотя модуль не требует подключения olelib. Более реальный пример из жизни: создание ActveX-объекта без регистрации библиотеки-сервера.
  6. Вообще, почитай какую-нибудь Сишную статью: в чём польза виртуальный функций и что из этого можно выжать. Теперь это же можно выжать и в VB.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 04.03.2011 (Пт) 5:41

ХакерУгу :) Где-то в этом направлении я сразу же и стал ковырять - см. ссылки, что я наковырял с заглавного сайта:
viewtopic.php?p=6752404#p6752404

Хакер писал(а):Более реальный пример из жизни: создание ActveX-объекта без регистрации библиотеки-сервера.
Ух ты!!!
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Antonariy » 04.03.2011 (Пт) 12:43

2, 3 и 5 не прикладные задачи, а кирпичи, из которых может строится решение прикладной задачи. Плагин ладно, это прикладная задача, хотя ему нафиг не сдались указатели, если только он не общается с хостом интенсивно в каком-нибудь цикле. Ну а если нужен ОЧЕНЬ быстрый парсер, то это совсем другие технологии, а не пенсионер VB6 на модных костылях.

"Все, что можно выжать" не требуется в небольших прикладных программах, на которые ориентирован VB6. Ну писались на нем какие-нибудь програмные монстры автоматизации, типа диасофта, и где те монстры? Вымерли все или эволюционировали/деградировали (нужное подчеркнуть) в .net.
Лучший способ понять что-то самому — объяснить это другому.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Antonariy » 04.03.2011 (Пт) 12:48

arthur2 писал(а):
Хакер писал(а):Более реальный пример из жизни: создание ActveX-объекта без регистрации библиотеки-сервера.
Ух ты!!!
Баян.
Лучший способ понять что-то самому — объяснить это другому.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Хакер » 04.03.2011 (Пт) 13:02

Antonariy писал(а):хотя ему нафиг не сдались указатели, если только он не общается с хостом интенсивно в каком-нибудь цикле

Да не плагину нужны, а при реализации хост-программы. Да ту же, ради примера, замену Explorer-а писать: нужно перечислить все элементы «Панели управления». В примере к проекту показано, как.

Antonariy писал(а):то это совсем другие технологии, а не пенсионер VB6

Подмывает спросить: да и что, что пенсионер? С++ старше. А Си — ещё старше. С чего ради возраст должен играть хоть какую-то ненулевую роль?

У меня логика такая: если вы уходите с VB, потому что в VB вам чего-то не хватает, скажите, чего вам не хватает, и я постараюсь сделать всё, чтобы привнести это в VB.
У вас же логика такая: нет смысла делать привнесение чего-либо в VB, потому что VB плох, потому что этого чего-либо в нём нет сейчас.

Баян

Речь же не о возможности сделать это, а в о том, чтобы делать это красиво. Некрасиво это делается у меня внутри FNDLL для создания инстанса CStdDLLInfo без регистрации скомпилированной DLL.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 04.03.2011 (Пт) 13:20

Когда появлась FireNativeDLL (три года назад), резонанс на форуме был :)
Antonariy писал(а):Титанически...
И изящно:
Интересно, почему сейчас ты не замечаешь изящества?

Почему обязательно надо высказаться в ключе "да кому это нужно"? Мне, например, нужно.
Артур
 
   

djalex777
Постоялец
Постоялец
 
Сообщения: 461
Зарегистрирован: 23.03.2006 (Чт) 16:02

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение djalex777 » 04.03.2011 (Пт) 15:15

Antonariy писал(а):Ну писались на нем какие-нибудь програмные монстры автоматизации, типа диасофта, и где те монстры? Вымерли все или эволюционировали/деградировали (нужное подчеркнуть) в .net.

Диасофт никогда не писал на VB, он не вымер и не перешел на .net. Всё писалось и пишется на дельфях. Писал для них множество модулей (по линии страховых компаний) в своё время :)

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Antonariy » 04.03.2011 (Пт) 16:48

Хакер писал(а):Да не плагину нужны, а при реализации хост-программы. Да ту же, ради примера, замену Explorer-а писать: нужно перечислить все элементы «Панели управления». В примере к проекту показано, как.
Не смотрел я его пока. Но все же да, это направление еще представляет интерес.
Хакер писал(а):Подмывает спросить: да и что, что пенсионер? С++ старше. А Си — ещё старше. С чего ради возраст должен играть хоть какую-то ненулевую роль?
Я имел ввиду не возраст, что-то вроде даты официального прекращения развития, последнего обновления. Старый софт это софт, который прекратил развитие <много> лет назад.
Хакер писал(а):У вас же логика такая: нет смысла делать привнесение чего-либо в VB, потому что VB плох, потому что этого чего-либо в нём нет сейчас.
Моя логика другая. VB не плох, если уметь им пользоваться. Есть смысл улучшать в нем что угодно, коль скоро это решает твои задачи, но не жди, что это заинтересует многих. Официально мертвая среда разработки отпугивает крупных заказчиков и, как следствие, большую часть разработчиков.

arthur2 писал(а):Когда появлась FireNativeDLL (три года назад), резонанс на форуме был :)
Antonariy писал(а):Титанически...
И изящно:
Интересно, почему сейчас ты не замечаешь изящества?
Я все это замечаю и сейчас. Просто Хакер спрашивает, почему нет комментариев? Потому что…
arthur2 писал(а):Почему обязательно надо высказаться в ключе "да кому это нужно"? Мне, например, нужно.
… это мало кому нужно.
А то, как он пишет, в комментариях, моих по крайней мере, не нуждается. :)
Лучший способ понять что-то самому — объяснить это другому.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение Antonariy » 04.03.2011 (Пт) 16:50

djalex777 писал(а):
Antonariy писал(а):Ну писались на нем какие-нибудь програмные монстры автоматизации, типа диасофта, и где те монстры? Вымерли все или эволюционировали/деградировали (нужное подчеркнуть) в .net.

Диасофт никогда не писал на VB, он не вымер и не перешел на .net. Всё писалось и пишется на дельфях. Писал для них множество модулей (по линии страховых компаний) в своё время :)

Значит я с кем-то его спутал. Лет 7-8 назад были VB-вакансии от какой-то подобной конторы.
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: Magic Pointers («красивые» указатели на функции, вызов)

Сообщение arthur2 » 04.03.2011 (Пт) 20:50

Хакер писал(а):возможность менять значени указателя есть
Есть, но не очень быстрая - поиск по строке. Ещё и ByVal :)

Я бы сдлелал (то есть, я себе так и переделал), чтобы FuncPointer принимала не имя указателя, а некий ID указателя - тогда присвоение указателю нового адреса, кроме первого раза, не будет связано с поиском по имени.

  • Объявление указателя дополняю объявлением его ID.
  • Добавил функцию IdPntFunc, которая по имени указателя возвращает непосредственно lpImportAddressesEntry.
  • FuncPointer вместо имени принимает значение, которое получено от IdPntFunc, то есть, принимает непосредственно lpImportAddressesEntry.

Код: Выделить всё
Private Declare Function pfTest Lib "*" (ByVal a As Long, ByVal b As Long) As Long
Private idPfTest As Long

Код: Выделить всё
    If idPfTest = 0 Then idPfTest = IdPntFunc("pfTest")
    FuncPointer(idPfTest) = addrOpAdd
Артур
 
   

След.

Вернуться в Наши проекты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 33

    TopList