Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 24, средняя оценка - 4.96
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
#1

Использование строк в макросах С++ - C++

11.02.2013, 13:19. Просмотров 3128. Ответов 23
Метки нет (Все метки)

Доброго времени суток всем!
Возникла небольшая проблема - не могу понять, возможно ли сделать нечто подобное, и, если возможно, то как.
Есть макрос, объявляющий функцию:

C++
1
2
3
4
#define DECLARE_FUNC(name1, body, type_cl, ...)\
    __declspec(dllexport) void type_cl name1##_func(__VA_ARGS__){\
    body;\
}\
Используется следующим образом:
C++
1
DECLARE_FUNC(testDeclare, "debug_msg(\"TestDeclare\",\"hello!\")", void, void);
где строка - вызов функции debug_msg(запись в файл форматированной строки).

Собственно, вопрос - как это сделать правильно? В текущем варианте нет никакой реакции на вызов функции testDeclare_func().

P.S. В следующем варианте
C++
1
2
3
4
5
#define DECLARE_FUNC(name1, body, type_cl, ...)\
    __declspec(dllexport) void type_cl name1##_func(__VA_ARGS__){\
    debug_msg("TestDeclare","hello!");\
    body;\
}\
вывод из debug_msg("TestDeclare","hello!"); вполне адекватно отрабатывает.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
vxg
Модератор
3120 / 1922 / 208
Регистрация: 13.01.2012
Сообщений: 7,360
11.02.2013, 14:09     Использование строк в макросах С++ #2
вы пытаетесь макросом объявить функцию и в то же время пытаетесь передать ей список аргументов. аргументы передаются во время вызова. наверное нужен макрос для вызова
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
11.02.2013, 15:28  [ТС]     Использование строк в макросах С++ #3
Какого рода макрос?
Если объявить функцию следующим макросом
C++
1
DECLARE_FUNC(testDeclare, "debug_msg(\"TestDeclare\",\"%d\", a1)", void, int a1);
и вызвать
C++
1
testDeclare(123);
то в файле получим вывод 123.

Или я неправильно понял смысл поста?
vxg
Модератор
3120 / 1922 / 208
Регистрация: 13.01.2012
Сообщений: 7,360
11.02.2013, 15:39     Использование строк в макросах С++ #4
вот во что будет преобразован макрос
C++
1
2
3
__declspec(dllexport) void void testDeclare_func(ЗДЕСЬ БУДЕТ АД - Я ДАЖЕ НЕ ЗНАЮ КАК ПРЕПРОЦЕССОР ОБРАБОТАЕТ INT A1){
    "debug_msg(TestDeclare,%d, a1)";
}
Добавлено через 1 минуту
__VA_ARGS__ можно было бы скормить вызову функции но не определению то есть
C++
1
CALL_MY_STRANGE_FUNC(name, __VA_ARGS__) name(__VA_ARGS__);
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
11.02.2013, 21:45  [ТС]     Использование строк в макросах С++ #5
Пардон, торопился, ошибся, когда в уме модифицировал.
Переделывал из рабочего макроса

C++
1
2
3
4
5
#define RF_O(ret, type_cl, name1, adres, ...)\
    typedef ret ( type_cl * t##name1 ) ( __VA_ARGS__ );\
    /*__declspec(dllexport) */t##name1 __declspec(dllexport) name1##_Detour = ( t##name1 ) ( adres );\
    __declspec(dllexport) void type_cl name1##_hook(__VA_ARGS__);\
    BYTE name1##_var[6];\

Реальный код таков:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#define DECLARE_FUNC(name1, body, type_cl, ...)\
    __declspec(dllexport) void type_cl name1##_func(__VA_ARGS__){\
    debug_msg("TestDeclare","hello!");\
    body;\
}\
 
 
#define RF_IMP(ret, type_cl, body, name1, ...)\
    DECLARE_FUNC(name1,body,type_cl, __VA_ARGS__);
 
char *declare = "debug_msg(\"TestDeclare\",\"hello!\")";
RF_IMP(void, __cdecl, declare,testDeclare,void);
В таком варианте полученная функция выглядит так:

C++
1
2
3
4
5
6
__declspec(dllexport) void __cdecl name1_func(void);
 
void __cdecl name1_func(void)
{
body;
}

Вот проблема в том, как обработать body.

P.S. Код рабочий, за исключением того, что не в курсе, как строку преобразовать в тело функции. Если подставить туда a1(ну или любые другие аргументы) + написать тело вручную, то все будет работать отлично. К примеру, аналогичный макрос предназначен для универсального парса lua_State перехваченных функций в 1 игрушке, использующей луа-движок.
nonedark2008
883 / 622 / 125
Регистрация: 28.07.2012
Сообщений: 1,662
11.02.2013, 22:14     Использование строк в макросах С++ #6
demogor, вы забываетесь. C/C++ - это компилируемые языки. Т.е. перед запуском куска кода - он должен быть скомпилирован! Т.е. невозможно выполнить в программе код, который помещен в текстовую строку. Это возможно в большинстве скриптовых языков, таких как Python, но никак не C++.
А при компиляции, компилятор возьмет строку RF_IMP(void, __cdecl, declare,testDeclare,void); затем преобразует ее в DECLARE_FUNC(testDeclare,declare,__cdecl, void); затем это преобразует в
__declspec(dllexport) void type_cl testDeclare_func( void ){
debug_msg("TestDeclare","hello!");
declare;
}
А затем полученный код он будет дальше компилировать. Т.е. как видно, вместо body подставиться просто строка теста, то никак не тело функции, которое вы хотите сделать.

Добавлено через 4 минуты
Стоит запомнить, что макросы никаким образом не работают с содержимым перменных, только с именами.
Например
C++
1
2
3
4
#define print(a, b) cout << a##b
void main( void ) {
  int x = 1, y = 2;
  split(x, y);
Результат будет не 12, как вы ожидаете, а ошибка компиляции, так как как видно в дефайне, он вместо a подставит x, вместо b - y, склеит их и получит xy. Т.е. в итоге попытается вывести переменную с именем xy, которая не определена.
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
11.02.2013, 22:17  [ТС]     Использование строк в макросах С++ #7
Понял, собственно это меня и интересовало, благодарю за ответ)
А есть ли возможность импорта тела функции из lua? Можно импортировать всю функцию, конечно, но это не самый идеальный вариант.
nonedark2008
883 / 622 / 125
Регистрация: 28.07.2012
Сообщений: 1,662
11.02.2013, 22:24     Использование строк в макросах С++ #8
demogor, ни разу не работал с Lua. Но как я понял - это скриптовый язык? Обычно, такое реализуется сторонней библиотекой. Что-то есть тут, что-то тут. Вообще много чего можно найти в гугле по запросу "Lua in C++".
Evg
Эксперт CАвтор FAQ
17470 / 5708 / 363
Регистрация: 30.03.2009
Сообщений: 15,670
Записей в блоге: 26
11.02.2013, 22:29     Использование строк в макросах С++ #9
Цитата Сообщение от demogor Посмотреть сообщение
Понял, собственно это меня и интересовало, благодарю за ответ)
А есть ли возможность импорта тела функции из lua? Можно импортировать всю функцию, конечно, но это не самый идеальный вариант.
Я не очень понимаю смысла фразы "импорта тела функции из lua". Если ты хочешь исполнить код Lua из-под Си/Си++, то можешь тут посмотреть: http://www.cyberforum.ru/cpp-builder/thread68085.html. В посте #8 конкретный пример (который никак не зависит от конкретного компилятора)
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
11.02.2013, 22:54  [ТС]     Использование строк в макросах С++ #10
Да не, как импортировать функции туда-обратно, я представляю. Хотел реализовать просто обертку для перехвата функций(много достаточно однотипных функций, объявлять их уже наловчился, было бы неплохо добавить возможность изменять код извне, что бы каждый раз не ребилдить dll'ку).
Evg
Эксперт CАвтор FAQ
17470 / 5708 / 363
Регистрация: 30.03.2009
Сообщений: 15,670
Записей в блоге: 26
12.02.2013, 00:01     Использование строк в макросах С++ #11
Что такое "обёртка для перехвата функций"?
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
12.02.2013, 00:24  [ТС]     Использование строк в макросах С++ #12
Неточно выразился.
Я имел в виду макросы для объявления функций, используемых для перехвата оригинальных функций.

C++
1
2
3
RF_O(void, __cdecl, lua_state, 0xCB62B0, lua_State *L, const char *libname, const luaL_Reg *l);
RF_O(void, __cdecl, luaLoadLibs, 0x8E9760, lua_State *L);
RF_O(void, __cdecl, lua_setfield, 0xCE63B0, lua_State *L, int index, const char *k);
К примеру.

Функции объявил, рассчитал адрес в памяти(если он не статический), поставил хук - и нужно бы описать функции, но пока это приходится делать вручную.
Правда, можно обойтись и простым логированием, для начала вполне сойдет.
Evg
Эксперт CАвтор FAQ
17470 / 5708 / 363
Регистрация: 30.03.2009
Сообщений: 15,670
Записей в блоге: 26
12.02.2013, 09:02     Использование строк в макросах С++ #13
Из этого тебе надо родить макрос RF_O? А что за константа в 4-м параметре? Есть такая умная мысль: "грамотно поставленный вопрос - это уже половина ответа". Я примерно понимаю, что тебе надо, но не пойму, что же конкретно

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

Код

C++
1
2
3
4
5
6
#define DECLARE_FUNC(name1, body, type_cl, ...) \
  __declspec(dllexport) type_cl name1##_func(__VA_ARGS__) {\
    body; \
  }
 
DECLARE_FUNC (testDeclare, debug_msg ("TestDeclare", "hello!"), void, int x, int y)
после препроцессора превратится в

C++
1
__declspec(dllexport) void testDeclare_func(int x, int y) { debug_msg ("TestDeclare", "hello!"); }
Правда я не пойму, чем такие извращения с макросами дают преимущество по сравнению с ручным описанием функции. Лично я ни одного преимущества не вижу

Добавлено через 1 минуту
Может вот это тебе чем-то поможет: http://www.cyberforum.ru/blogs/18334/blog100.html
nonedark2008
883 / 622 / 125
Регистрация: 28.07.2012
Сообщений: 1,662
12.02.2013, 10:07     Использование строк в макросах С++ #14
Evg, как я понял, у него есть библиотееа на C++. Но ее нужно очень часто менять, но ему очень не хочется постоянно ее перекомпилировать для этого. Поэтому он хочет, чтобы внутри его библиотеки использовались функции из скриптового языка. Т. е. можно поменять что-то в библиотеке просто изменив функции в скрипте.
Kastaneda
12.02.2013, 10:18
  #15

Не по теме:

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

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#define DEFINE_ENUM_MAP(type,descr) \
template<>\
const char* toString<type>(type e) {\
    cnvResult = true;\
    for(uint16 i = 0; i < g##type##Len; i++) {\
        if (g##type##Names[i].e == e) {\
            return g##type##Names[i].s;\
        }\
    }\
    cnvResult = false;\
    /* warning("Value %d for type %s has no string representation", e, #type); */ \
    return NULL;\
}\
\
template<>\
type fromString<type>(const char* s, type def) {\
    cnvResult = true;\
    for(uint16 i = 0; i < g##type##Len; i++) {\
        if (!strcmp(g##type##Names[i].s,s)) {\
            return g##type##Names[i].e;\
        }\
    }\
    warning("Can not convert string \"%s\" to value of type %s", s, #type);\
    cnvResult = false;\
    return (type)def;\
}\
\
template<> string getAllStrings<type>(const type* e, uint16 size){\
    string res;uint16 i;\
    if ( !e || !size ) {\
        if (size) {\
            res = #type;\
        } else {\
            for(i = 0; i < g##type##Len; i++) {\
                if ( i > 0 ) res += ',';\
                res += g##type##Names[i].s;\
            }\
        }\
    } else  {\
        res = arrToString<type>(e,size);\
    }\
    return res;\
}\
\
template<>\
const char* getTypeDescription<type>(type e) {return g##type##Descrip;}\
\
template<>\
string getAllItemsDescription<type>(type e) {\
    string res;uint16 i,c=0;\
    for(i = 0; i < g##type##Len; i++) {\
        if ( c > 0 ) res += '\n';\
        if ( g##type##Names[i].d ) {\
            res += g##type##Names[i].s;\
            res += '\t';\
            res += g##type##Names[i].d;\
            c++;\
        }\
    }\
    return res;\
}\
\
template<>\
const char* getItemDescription<type>(type e) {\
    for(uint16 i = 0; i < g##type##Len; i++) {\
        if (g##type##Names[i].e == e) {\
            return g##type##Names[i].d;\
        }\
    }\
    return 0;\
}\
\
const char* g##type##Descrip=descr;\
const CTG##type##Map g##type##Names[g##type##Len] = {
 
// Closing macro for enum to string mapping
#define END_ENUM_MAP }

vxg
Модератор
3120 / 1922 / 208
Регистрация: 13.01.2012
Сообщений: 7,360
12.02.2013, 10:46     Использование строк в макросах С++ #16
Цитата Сообщение от Evg Посмотреть сообщение
после препроцессора превратится в
я думал что препроцессор споткнется об запятую перед hello, но пример работает. как это возможно?
Evg
Эксперт CАвтор FAQ
17470 / 5708 / 363
Регистрация: 30.03.2009
Сообщений: 15,670
Записей в блоге: 26
12.02.2013, 22:05     Использование строк в макросах С++ #17
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Evg, как я понял, у него есть библиотееа на C++. Но ее нужно очень часто менять, но ему очень не хочется постоянно ее перекомпилировать для этого. Поэтому он хочет, чтобы внутри его библиотеки использовались функции из скриптового языка. Т. е. можно поменять что-то в библиотеке просто изменив функции в скрипте.
Ну... при такой постановке вопроса в компилируемых языках настолько просто это не решается.

Цитата Сообщение от vxg Посмотреть сообщение
я думал что препроцессор споткнется об запятую перед hello, но пример работает. как это возможно?
Слушай, хороший вопрос. Мне казалось чем-то самим собой разумеющимся то, что наличие скобок экранирует запятые. Причём наверняка оно так и есть, но я как-то никогда об этом не задумывался, просто использовал и всё. Надо бы почитать
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
12.02.2013, 22:29  [ТС]     Использование строк в макросах С++ #18
Evg, если о lua_State(
А что за константа в 4-м параметре?
), то это состояние текущего экземпляра луа интерпретатора. Честно говоря, сам не до конца понимаю смысла его, потому представляю как некий контейнер, содержащий аргументы lua функции(стек, по факту).
Вариант подачи тела, предоставленный выше, логичен, но хотелось именно строку передавать, что бы была возможность вытягивать тело функции из отдельного файла(nonedark абсолютно прав).
Необходимость этого в том, что я разбираю потихоньку клиент и для получения информации о функциях их необходимо перехватывать. Каждый раз, что бы это сделать, необходимо описывать функции - а это не слишком удобно. Именно для этого и нужны макросы, потому и хочу максимально автоматизировать процесс.
Более того, в принципе, для начала меня вполне устроит макрос, который будет объявлять и описывать функцию с выводом аргументов в файл при перехвате.
Evg
Эксперт CАвтор FAQ
17470 / 5708 / 363
Регистрация: 30.03.2009
Сообщений: 15,670
Записей в блоге: 26
12.02.2013, 22:39     Использование строк в макросах С++ #19
Цитата Сообщение от demogor Посмотреть сообщение
Вариант подачи тела, предоставленный выше, логичен, но хотелось именно строку передавать, что бы была возможность вытягивать тело функции из отдельного файла(nonedark абсолютно прав)
Для компилируемого языка сие попросту нормально не реализуемо. Единственный способ - это из программы сгенерить файл на Си, далее из программы же вызвать компилятор и сформировать динамическую библиотеку, далее из программы же эту библиотеку подключить (в unix-системах есть интерфейс dlopen и ко, наверняка в винде есть то же самое). Либо использовать всякие нанотехнологии типа OpenCL, которые по большому счёту точно так же являются вызовом компилятора, только всё это монолитно встраивается в программу.

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

Добавлено через 1 минуту
А в целом я твою задачу всё равно не понимаю из-за невнятной постановки

Ну или могу порекомендовать на ходу генерировать функции на Lua, а не на Си. Интерпретатор Lua встраивается в программу, а потому сие вполне допустимо
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.02.2013, 22:49     Использование строк в макросах С++
Еще ссылки по теме:
Использование строк, как одномерные массивы символов C++
C++ функция возвращает int, возвращаемые значения определены в макросах, как сразу выводить определённые макросы?
C++ Л/р "Использование строк"
C++ По некоторому количеству строк (не более N) найти пары строк с общим словом
C++ Вводится массив строк текста с неизвестным заранее количеством строк

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
12.02.2013, 22:49  [ТС]     Использование строк в макросах С++ #20
Я хочу добавлять хуки сразу из луа, но для этого нужно как-то описывать тело функции(а не только ее декларировать). Вариант с подачей из текстового файла сначала показался самым подходящим но, как я уже понял, это не представляется возможным.
Впрочем, думаю, мне вполне хватит варианта с выводом аргументов.
Yandex
Объявления
12.02.2013, 22:49     Использование строк в макросах С++
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru