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

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

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

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

11.02.2013, 13:19. Просмотров 3246. Ответов 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!"); вполне адекватно отрабатывает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.02.2013, 13:19
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Использование строк в макросах С++ (C++):

Использование строк.Использование структур - C++
Задачка: Дана строка,состоящая из групп нулей и едениц. Найти и вывести на экран группы с нечетным количеством символов. И еще одна: ...

Использование строк - C++
Помогите с алгоритмом программы: вводим текст происходит проверка на наличие цифр прописью, заменяет их и выводит исправленый...

Использование файлов и строк - C++
Уважаемые программисты! Нужна ваша помощь, заканчиваю написание диплома и возникла следующая проблемка: Есть программа, которая все...

Использование строк и файлов - C++
С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна...

Использование собственного класса строк - C++
Здравствуйте, уважаемые господа. Есть реализация собственного класса строк: class MyString { private: size_t length; ...

Использование функций обработки строк - C++
Напишите кто может прогу плиз.. Дана строка текста, в которой слова разделены пробелами и запятыми. Необходимо: вычислит количество...

23
vxg
Модератор
3169 / 1972 / 221
Регистрация: 13.01.2012
Сообщений: 7,577
11.02.2013, 14:09 #2
вы пытаетесь макросом объявить функцию и в то же время пытаетесь передать ей список аргументов. аргументы передаются во время вызова. наверное нужен макрос для вызова
0
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.

Или я неправильно понял смысл поста?
0
vxg
Модератор
3169 / 1972 / 221
Регистрация: 13.01.2012
Сообщений: 7,577
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__);
0
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 игрушке, использующей луа-движок.
0
nonedark2008
914 / 653 / 136
Регистрация: 28.07.2012
Сообщений: 1,767
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, которая не определена.
1
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
11.02.2013, 22:17  [ТС] #7
Понял, собственно это меня и интересовало, благодарю за ответ)
А есть ли возможность импорта тела функции из lua? Можно импортировать всю функцию, конечно, но это не самый идеальный вариант.
0
nonedark2008
914 / 653 / 136
Регистрация: 28.07.2012
Сообщений: 1,767
11.02.2013, 22:24 #8
demogor, ни разу не работал с Lua. Но как я понял - это скриптовый язык? Обычно, такое реализуется сторонней библиотекой. Что-то есть тут, что-то тут. Вообще много чего можно найти в гугле по запросу "Lua in C++".
0
Evg
Эксперт CАвтор FAQ
17941 / 6172 / 411
Регистрация: 30.03.2009
Сообщений: 16,942
Записей в блоге: 27
11.02.2013, 22:29 #9
Цитата Сообщение от demogor Посмотреть сообщение
Понял, собственно это меня и интересовало, благодарю за ответ)
А есть ли возможность импорта тела функции из lua? Можно импортировать всю функцию, конечно, но это не самый идеальный вариант.
Я не очень понимаю смысла фразы "импорта тела функции из lua". Если ты хочешь исполнить код Lua из-под Си/Си++, то можешь тут посмотреть: http://www.cyberforum.ru/cpp-builder/thread68085.html. В посте #8 конкретный пример (который никак не зависит от конкретного компилятора)
0
demogor
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 10
11.02.2013, 22:54  [ТС] #10
Да не, как импортировать функции туда-обратно, я представляю. Хотел реализовать просто обертку для перехвата функций(много достаточно однотипных функций, объявлять их уже наловчился, было бы неплохо добавить возможность изменять код извне, что бы каждый раз не ребилдить dll'ку).
0
Evg
Эксперт CАвтор FAQ
17941 / 6172 / 411
Регистрация: 30.03.2009
Сообщений: 16,942
Записей в блоге: 27
12.02.2013, 00:01 #11
Что такое "обёртка для перехвата функций"?
0
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);
К примеру.

Функции объявил, рассчитал адрес в памяти(если он не статический), поставил хук - и нужно бы описать функции, но пока это приходится делать вручную.
Правда, можно обойтись и простым логированием, для начала вполне сойдет.
0
Evg
Эксперт CАвтор FAQ
17941 / 6172 / 411
Регистрация: 30.03.2009
Сообщений: 16,942
Записей в блоге: 27
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
0
nonedark2008
914 / 653 / 136
Регистрация: 28.07.2012
Сообщений: 1,767
12.02.2013, 10:07 #14
Evg, как я понял, у него есть библиотееа на C++. Но ее нужно очень часто менять, но ему очень не хочется постоянно ее перекомпилировать для этого. Поэтому он хочет, чтобы внутри его библиотеки использовались функции из скриптового языка. Т. е. можно поменять что-то в библиотеке просто изменив функции в скрипте.
0
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 }

1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.02.2013, 10:18
Привет! Вот еще темы с ответами:

Использование одномерного массива строк - C++
Здравствуйте! Задание: Имеется файл 1.txt в котором содержатся строки неизвестной длины. Так же имеется файл 2.txt в котором так же...

Метки в макросах в ассемблерной вставке - C++
В C++ написан макрос с ассемблерной вставкой, который содержит в себе метку &quot;doit&quot; и команду перехода на неё: #define MYMACRO(x, y, z)...

Использование указателей на функцию для обработки строк - C++
#include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;iostream&gt; using namespace std; void check(char *a, char *b, int...

Использование строк, как одномерные массивы символов - C++
Вот такая задачка Дана строка символов, состоящая из цифр, разделенных пробелами. Вывести четные числа этой строки Это оконный режим...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
12.02.2013, 10:18
Ответ Создать тему
Опции темы

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