| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Генерирование функций |
| Автор: Lipetsk 3.11.2011, 07:51 | ||
| Здравствуйте У меня возникла такая задача на C/C++. Нужно сделать что-то вроде генератора функций. Например,
Наверняка для этого существуют какие-то стандартные подходы, но в интернете что-то ничего удовлетворительного не нашел Спасибо |
| Автор: Earnest 3.11.2011, 08:03 | ||||
| Во-первых, это надо спрашивать в разделе С++ Во-вторых, можно как-то так:
Использование:
|
| Автор: Lipetsk 3.11.2011, 08:16 |
| на счет раздела, может я и ошибся но ваш вариант реализации определенно не годится, нужно именно "генерировать" функции в real-time, а не при компиляции нужно, чтобы функция f имела определенный тип, в примере это func, потому что это будет CallBack функция для API |
| Автор: Lipetsk 3.11.2011, 08:37 |
| Если я ошибся разделом, то, пожалуйста, перенесите тему в раздел C/C++ Общие вопросы |
| Автор: Earnest 3.11.2011, 09:41 |
С++ так не умеет. А что касается раздела, то это может сделать только его модератор. |
| Автор: boostcoder 3.11.2011, 10:33 | ||
| как сказала Earnest, в с++ невозможно генерировать функции в run-time. но это собственно и не надо. одно из решений:
http://liveworkspace.org/code/3a57b623742d384def3c92ebca38b115 |
| Автор: boostcoder 3.11.2011, 11:03 |
обоснование, пожалуйста ;) |
| Автор: Lipetsk 3.11.2011, 11:16 |
я уже писал |
| Автор: Леопольд 3.11.2011, 11:20 | ||||
А чем предложенный вариант не подходит?
|
| Автор: Lipetsk 3.11.2011, 11:24 | ||||
Леопольд, вы не видите разности между
и
? |
| Автор: Леопольд 3.11.2011, 11:26 | ||
Голый указатель на функцию это из мира чистого С, в котором нет поддержки ООП. Если не нравится boost::function и не хочется привязываться к сторонней библиотеке, можно использовать шаблоны:
|
| Автор: Lipetsk 3.11.2011, 11:43 | ||
А мне и не нужно ООП например, мне нужно в классе вызвать DdeInitialize и передать ему уникальную callback функцию, привязанную к экземпляру класса, а не статическую. Эту уникальную функцию в принципе можно сгенерировать используя ассемблерные вставки в код. Но не очень хочется изобретать велосипед, хотя |
| Автор: boostcoder 3.11.2011, 12:19 |
| Lipetsk, а диапазон значений для функции Generator(), известен? |
| Автор: Lipetsk 3.11.2011, 12:44 | ||
я не понял вопроса ее значения это функции много ли экземпляров функций f я собираюсь создать? пока не много но скоро мне нужно будет заняться одной задачей с COM-объектами, в которой, я планирую, будет аналогичный генератор и вызывать его я буду постоянно (а также удалять отработавшие функции) |
| Автор: Леопольд 3.11.2011, 12:58 | ||
|
| Автор: Lipetsk 3.11.2011, 13:30 |
А директивы компилятора на что? |
| Автор: bsa 3.11.2011, 13:45 |
какие например? И вообще, какие стандартные (читай переносимые) директивы компилятора ты знаешь? |
| Автор: math64 3.11.2011, 14:05 | ||
Как раз важно сколько экземпляров функции нужно создать. если оно ограничено, то можно.
|
| Автор: mes 3.11.2011, 14:55 |
| Lipetsk, Вы не очень четко сформулировали задачи, поэтому Вас не понимают и предлагают пол-решения.. Вы б вместо того чтоб возмущаться на счет типов лучше бы прояснили немного.. Я так понимаю Вам нужен коллбяк посредник, дополняющий к аргументам, еще свой идентификатор.. так ? |
| Автор: mes 3.11.2011, 15:12 |
| алсо наглядный пример вызова функции (без использования ваших идей с генератором) был бы в помощь.. т.е. Вам нужно точно определить, что есть на входе, и что Вамнужно на выходе и тогда можно будет ответить как этого добиться оптимальным способом.. Добавлено через 56 секунд насчет невозможности переносимого решения, написано не (совсем ) правда.. |
| Автор: boostcoder 3.11.2011, 15:40 |
| Lipetsk, объясни нормально задачу. не верю я что тебе реально нужен генератор каких-то функций. |
| Автор: baldina 3.11.2011, 15:55 |
| имхо ему нужно доп. параметры в колбэк передавать, а DdeInitialize такой возможности не предоставляет. Вот и выдумывает "генерацию функций" |
| Автор: bsa 3.11.2011, 16:04 |
| Lipetsk, скорее всего, такое сделать просто нельзя, так как предполагается, что DdeInitialize вызывается единожды для приложения (я ошибаюсь?), поэтому все данные коллбэка должны быть статическими, так как он един для всего процесса. Если ты не знаешь, как это сделать с классами - почитай про PIMPL. |
| Автор: Lipetsk 3.11.2011, 22:33 | ||
суть такая, но нужна динамика, а не фиксированный набор функций возможно, что вызов DdeInitialize "затирает" предыдущий вызов, проверить смогу только в понедельник но можно придумать и другие варианты задач, когда такое необходимо, и меня интересует, как такое реализовывается пусть DdeInitialize можно вызывать несколько раз, как тогда быть? но я уже кое-что нашел http://www.hackcraft.net/cpp/windowsThunk/ и http://www.codeproject.com/KB/cpp/Thunk_uses.aspx |
| Автор: mes 3.11.2011, 23:37 |
в примерах идет отражение хэндлов системы на указатели клиента.. Это не совсем то что вы описывали вначале.. под ваше описание подходят несколько вариантов задач, чтобне перебирать все, желательно бы от Вас услышать более точное условие. |
| Автор: Lipetsk 4.11.2011, 10:36 |
| Вот мое точное условие В случае, когда функции не генерируются динамически, а создаются заранее получается примерно так (мне это не нужно, даю ссылку для лучшего понимания задачи) |
| Автор: mes 4.11.2011, 10:47 |
| Lipetsk, в цитатнике текста не видно.. |
| Автор: boostcoder 4.11.2011, 12:30 |
все потому, что его там нет. |
| Автор: math64 4.11.2011, 12:55 | ||
Динамически создать функцию в условиях Windows не пролучится, даже с ассемблером, в DOS было можно примерно так:
в Windows так не получится, поскольку у сгенерированного кода не будет прав на выполнение. |
| Автор: baldina 4.11.2011, 13:26 |
тогда каждый вызов DdeInitialize обязательно будет связан с уникальным идентификатором |
| Автор: mes 4.11.2011, 14:49 | ||||||
насколько я понял, имеется некое апи с колбяком, допустим :
нужно чтоб можно было привязать функцию печатающее число, где число задаются рантайм значением ..- такое условие ? тогда решение может быть таким :
http://liveworkspace.org/code/2bc57970c9075670290cdc23bf2871eb |
| Автор: math64 4.11.2011, 15:28 | ||
mes, зачеи эти извращения? они экивалентны
т.е. при повторном вызове с другим аргументом быдет вызываться не та функция. (API использует переданную функцию не в самом вызове api(), а запоминает её и вызывает позже) |
| Автор: mes 4.11.2011, 15:43 |
для визуальной эквивалентности апи-надстройки к базовому апи да и чтоб автору был повод пересмотреть свое отношение к полноте задаваемого вопроса.. тс несколько раз просили сформулировать задачу, он _вежливо_ отказался, поэтому решал ее со своей колокольни |
| Автор: mes 4.11.2011, 16:05 | ||
ну раз то извращение, тогда добавлю еще http://liveworkspace.org/code/7fbb6089dd53eae19c9ee68628744793 Добавлено @ 16:06
или так в двух вариантах : http://liveworkspace.org/code/0ed044826500e39651a435224322268c ух сколько наболтал: 7007 |
| Автор: math64 4.11.2011, 19:04 | ||||||
Я бы не назвал это извращением, если бы оно решало проблему. API скорее всего имееи вид:
Обычно делают так:
Тогда использование выглядит так:
Но если у callback не предусмотрен лишний аргумент, возникает проблема с его использованием. Если число экземпляров Callback ограничено - решение см. мой пост на предыдущей странице. |
| Автор: mes 4.11.2011, 21:39 | ||
| math64, попробую разобраться что Ва написали.. напервый взгляд выглядит немного несвязанно.. Добавлено через 5 минут и 44 секунды вроде понял о чем Вы.. Добавлено через 11 минут и 17 секунд вообщем требуется чтоб заработал такой условный код с расскомментированной строкой
|
| Автор: Lipetsk 7.11.2011, 11:20 | ||
а у меня получается, и функция в области данных выполняется нормально |
| Автор: boostcoder 7.11.2011, 11:27 |
| Lipetsk, показывай решение. |
| Автор: Lipetsk 7.11.2011, 11:47 | ||
| полного решения пока нет, не дают "работать" но такой код легко выполняется
т.е. в буфер c можно записать что угодно и потом выполнить как функцию |
| Автор: math64 7.11.2011, 12:01 |
| В Линуксе такое не работает - "Ошибка сегментирования"; в Windows тоже не должно бы, только в режиме DOS. Добавлено через 14 минут и 21 секунду А если и получается - это дыра в защите Windows. Как только её закроют, работать перестанет. |
| Автор: bsa 7.11.2011, 13:00 | ||
где-то кто-то говорил, что ряд компиляторов (или это особенность именно ОС?) (МС в частности) размещает Си-строки в записываемой области памяти в целях совместимости со старым кривым софтом.
Совсем не факт. Страницы памяти, предназначенной для хранения данных (а строка именно в такой области), не предназначены для выполнения кода. С другой стороны, страницы памяти предназначенных для хранения кода не предназначены для записи. Другими словами, попытка скопировать функцию в область данные (теоретически, такое тоже может привести к ошибке сегментирования, так как область кода может быть нечитаемой) ничем для тебя не закончится, так как при попытке передать туда управление система быстро прикроет твое приложение. |
| Автор: boostcoder 7.11.2011, 13:15 |
| Lipetsk, это тупиковое решение. ищи другое |
| Автор: bsa 7.11.2011, 13:33 |
| Имхо, надо искать решение вообще в другой области. Что-то есть у меня подозрение, что DdeInitialize приложению достаточно вызвать всего один раз... А не на каждый чих. Возможно, даже система так устроена, что не предполагается более одного обработчика сообщений для приложения. Если уж нужно делать несколько обработчиков, то можно сделать диспетчер сообщений. Все обработчики при создании регистрируются в нем, а при уничтожении отменяют регистрацию. Когда приходит сообщение, то диспетчер выбирает подходящий обработчик (или перебирает все, пока кто-то не обработает) и его вызывает. В этом случае callback всего один - статический приватный метод диспетчера. |
| Автор: Earnest 7.11.2011, 13:45 | ||||
Не закроют, ибо совместимость. Это называется DEP (data execution protection) и регулируется в настройках ОС. На серверах по умолчанию запрещено, на рабочих станциях - разрешено, но и там и там регулируется. Но по сути - запуск на выполнение "данных" нужно использовать аккуратно, и только если того настоятельно требует задача (в целях защиты, например). Для данной же задачи - решение неудачное. |
| Автор: Lipetsk 7.11.2011, 13:48 |
| Я уже и сам понимаю, что такое не должно работать, хоть оно и работает Просто казалось, что "Генераторы функций" Всем большое спасибо за участие |