Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как передать функции несколько параметров, количество и тип параметров произвольный 
:(
    Опции темы
YouROK
Дата 29.12.2011, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 21.7.2011

Репутация: нет
Всего: нет



Есть строка допустим "printf(\"%s %d\"); chars:\"Hello world\", int:25;"

Моя функция парсит строку
получаем строку 
char *paramstr = "%s %d"
и список или что то в этом роде пока еще не определился
1)char* "Hello world"
2)int 25

далее идет вызов
printf(paramstr,тут как-то надо вставить эти параметры);

думал как-нибудь собрать va_list но там работа со стеком, что без ассемблера не сделаешь????

подскажите кто-нибудь, может через boost можно как-то или стандартными способами c++?

Это сообщение отредактировал(а) YouROK - 29.12.2011, 15:27
PM MAIL   Вверх
boostcoder
Дата 29.12.2011, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



нифига не понял smile 
PM WWW   Вверх
YouROK
Дата 29.12.2011, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 21.7.2011

Репутация: нет
Всего: нет



в программу ко мне по сети приходит строка
 "printf(\"%s %d\"); chars:\"Hello world\", int:25;"
моя программа должна вызвать функцию с этими аргументам
функция одна, а вот аргументы все время разные и количество их тоже меняется.
PM MAIL   Вверх
boostcoder
Дата 29.12.2011, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(YouROK @  29.12.2011,  15:35 Найти цитируемый пост)
chars:\"Hello world\", int:25;

распарсив эту часть, ты получаешь массив указателей на токены, и узнаешь кол-во аргументов. далее, итерируйся по списку полученных указателей и выводи при помощи std::cout
PM WWW   Вверх
YouROK
Дата 29.12.2011, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 21.7.2011

Репутация: нет
Всего: нет



Цитата(boostcoder @  29.12.2011,  15:50 Найти цитируемый пост)
выводи при помощи std::cout

printf был взят для примера
мне нужно именно передать все полученные параметры в функцию допустим в 
function1(char*str,...);
или
function1v(char *str, va_list *list);

Это сообщение отредактировал(а) YouROK - 29.12.2011, 16:04
PM MAIL   Вверх
boostcoder
Дата 29.12.2011, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



так передай в функцию список указателей. в чем сложность?
PM WWW   Вверх
bsa
Дата 29.12.2011, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



YouROK, такое действительно можно делать или на ассемблере, или перебирать в коде все возможные варианты (т.е. сделать код для всех возможных комбинаций параметров).

Мой тебе совет, пересмотри вообще постановку задачи, так как подобное решение не только трудно реализуемо, но и сильно снижает надежность кода.
PM   Вверх
boostcoder
Дата 29.12.2011, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(bsa @  29.12.2011,  16:36 Найти цитируемый пост)
или перебирать в коде все возможные варианты

варианты чего? он получает строки. варианты строк? smile 

Цитата(bsa @  29.12.2011,  16:36 Найти цитируемый пост)
(т.е. сделать код для всех возможных комбинаций параметров)

т.е. перегрузить функцию для всех возможных типов и количеств аргументов?. повторяю: он получает только строки.
PM WWW   Вверх
bsa
Дата 29.12.2011, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



варианты наборов аргументов функций.
PM   Вверх
YouROK
Дата 29.12.2011, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 21.7.2011

Репутация: нет
Всего: нет



Видимо придется делать 6 функций с разным количеством параметров, думаю больше 5 аргументов не будет.
PM MAIL   Вверх
boostcoder
Дата 29.12.2011, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



зачем?
PM WWW   Вверх
xvr
Дата 3.1.2012, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



В gcc есть встроенные функции, которые (судя по названию) умеют делать нечто подобное. См тут

PM MAIL   Вверх
feodorv
Дата 6.1.2012, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Теоретически, можно постараться реализовать всё это через va_list. Однако в таком случае передача неверных аргументов может завершить Вашу программу сигфолтом. Как минимум, Вам придётся проверять соответствие форматов в строке printf и передаваемых ей аргументов. То есть разбирать форматную строку.

Я всё же предлагаю реализовать задачу иначе. Простите, запишу всё через struct, легко можно будет перепесать и через классы.
  • завести понятие аргумент функции типа 
    Код

    struct farg
    {
      int type;
      int length;
      union anyvalue value;
    };

    где в anyvalue будут находится значения аргумента в зависимости от его типа type. Очевидные типы - int и string. Можно ввести какие-нибудь свои специфические.
  • функции-обработчики удалённых вызовов определять не через va_list, а через struct farg:
    Код

    rfunction(struct farg *list, int count);

  • собственно список аргументов создавать при парсинге приходящей строки.
  • для реализации printf придётся самому делать разбор форматной строки. Это не так уж и сложно, для начала можно ограничиться тремя форматами - %%, %s, %d, затем добавить обработку желаемых флагов при форматах, потом можно добавить и свои форматы, отсутствующие в стандартной printf и т.д.
  • для унификации вызов собственного printf осуществлять через команду "printf, chars:"%s %d", chars:"Hello world", int:25;", затем просто проверять, чтобы первый аргумент всегда был строкой.
Как-то так...

Это сообщение отредактировал(а) feodorv - 6.1.2012, 23:53


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
xvr
Дата 6.1.2012, 23:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Вариант с va_list имеет еще один недостаток - этот самый va_list очень компиляторно и системное зависим. Недавно столкнулся - на 64х битном х86 этот самый лист не void*, как у всех, а массив (из 1 элемента) весьма развесистой структуры

PM MAIL   Вверх
586
Дата 7.1.2012, 07:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 10
Всего: 146



Код
#include <stdarg.h>

int my_printf(const char *format, ...)
{
    int n;
    va_list v;
    va_start(v, format);
    n=vprintf(format, v);
    va_end(v);
    return n;
}

int main()
{
    my_printf("%s %d", "abc", -2);
    return 0;
}

PM   Вверх
YouROK
Дата 13.1.2012, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 21.7.2011

Репутация: нет
Всего: нет



feodorv
В том то и дело что функции которые принимают аргументы не мои и их изменить нельзя,
в конце концов сделал парсинг из строки в вектор типа boost::any
и сделал 7 вызовов функций, в зависимости от количества аргументов вызывается та или иная функция.
правда получилось немного коряво, но все работает.

Думаю вопрос интересный, может кто еще предложит идеи.

Интересует как это можно сделать на ассемблере, есть кто разбирается, может выложит хоть что нибудь?
Пусть и архетектурнозависимо

Добавлено через 4 минуты и 5 секунд
Цитата(586 @  7.1.2012,  07:45 Найти цитируемый пост)
#include <stdarg.h>
int my_printf(const char *format, ...)
{
    int n;
    va_list v;
    va_start(v, format);
    n=vprintf(format, v);
    va_end(v);
    return n;
}
int main()
{
    my_printf("%s %d", "abc", -2);
    return 0;
}

Суть в том что количество аргументов("abc",-2 у тебя их два) у меня все время разное
PM MAIL   Вверх
586
Дата 13.1.2012, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 10
Всего: 146



Цитата(YouROK @  13.1.2012,  15:13 Найти цитируемый пост)
Суть в том что количество аргументов("abc",-2 у тебя их два) у меня все время разное 

В функцию my_printf можно сколько угодно аргументов передать.
PM   Вверх
xvr
Дата 13.1.2012, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(YouROK @  13.1.2012,  14:13 Найти цитируемый пост)
Интересует как это можно сделать на ассемблере, есть кто разбирается, может выложит хоть что нибудь?
Пусть и архетектурнозависимо

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

PM MAIL   Вверх
500mhz
Дата 13.1.2012, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


шайтан
***


Профиль
Группа: Завсегдатай
Сообщений: 1017
Регистрация: 5.5.2008
Где: Киев / Italy

Репутация: нет
Всего: 14



ну можно внутри функции сравнить значение стека, и понять сколько аргументов там лежит

пример

Код

изначально к примеру esp = 1000

stdcall MyFunc,arg,arg,arg,arg


MyFunc:
mov ebx,esp     // текуший адрес стека
mov eax,1000  // предыдущий адрес стека
sub eax,ebx     // вычитаем
sub eax,4           // отнимаем 4 так как там кроме аргументов адрес возврата
shr eax,2          // делим на 4 - в случае если у на 4 байтные аргументы
                           // в ЕАХ колво аргументов
.......
ret


Это сообщение отредактировал(а) 500mhz - 13.1.2012, 21:00


--------------------

PM MAIL ICQ   Вверх
bsa
Дата 13.1.2012, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



500mhz, откуда ты взял "предыдущий адрес стека"?
PM   Вверх
500mhz
Дата 13.1.2012, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


шайтан
***


Профиль
Группа: Завсегдатай
Сообщений: 1017
Регистрация: 5.5.2008
Где: Киев / Italy

Репутация: нет
Всего: 14



ну допустим пусть он передаеться в ЕАХ при вызове функции


--------------------

PM MAIL ICQ   Вверх
bsa
Дата 13.1.2012, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



500mhz, интересно, а какой это тип вызова функции такой? что-то я не помню.
А потом, количество и тип аргументов известен на этапе выполнения.
PM   Вверх
boostcoder
Дата 13.1.2012, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(bsa @  13.1.2012,  23:46 Найти цитируемый пост)
количество и тип аргументов известен на этапе выполнения.

нет же.
стек формируется компилятором.
PM WWW   Вверх
xvr
Дата 14.1.2012, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  13.1.2012,  23:54 Найти цитируемый пост)
нет же.
стек формируется компилятором. 

У ТС задача обратная - у него известны параметры (run-time), надо самому сформировать стек для вызова

Если никакие параметры не передаются в регистрах (все в стеке), и они все (вне зависимости от типа) одинаковой длинны (с учетом выравнивания при помещении в стек), то такой вызов можно сформировать. 

Нужно просто явно вычислить все параметры (с первого или с последнего, в зависимости от типа вызова), и запихнуть их в стек (командой push). Потом позвать функцию, как void (*)(void). Если тип функции был cdecl, то после возврата надо сбросить стек (через add sp,<size>)


PM MAIL   Вверх
500mhz
Дата 14.1.2012, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


шайтан
***


Профиль
Группа: Завсегдатай
Сообщений: 1017
Регистрация: 5.5.2008
Где: Киев / Italy

Репутация: нет
Всего: 14



ха, с gcc не прокатывает он компилит нечто типа

Код

mov [esp+24],arg
mov [esp+20],arg1
call func

может есть какие то ключи для компиляции с push ?


--------------------

PM MAIL ICQ   Вверх
xvr
Дата 14.1.2012, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(500mhz @  14.1.2012,  15:28 Найти цитируемый пост)
ха, с gcc не прокатывает он компилит нечто типа

Это неважно - вызываемая функция ожидает найти параметры в стеке, и она их там найдет. То, что они туда попадут не так, как это делает gcc роли не играет, главное что бы ничего не сломалось


PM MAIL   Вверх
500mhz
Дата 14.1.2012, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


шайтан
***


Профиль
Группа: Завсегдатай
Сообщений: 1017
Регистрация: 5.5.2008
Где: Киев / Italy

Репутация: нет
Всего: 14



xvr
правильно аргументы на стеке, но сам стек нифига не меняеться 


--------------------

PM MAIL ICQ   Вверх
xvr
Дата 15.1.2012, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(500mhz @  14.1.2012,  19:35 Найти цитируемый пост)
но сам стек нифига не меняеться  

gcc заранее резервирует необходимое место на стеке (в прологе функции). Но ничего не мешает это место дополнительно алоцировать в процессе вызова функции (теми самыми push'ами)

Кстати, для __stdcall типа вызова gcc явно резервирует место в стеке (хотя и не с помощью push, но резервирует)
Код

extern void __stdcall func(int,int,int);

void tst(int a, int b, int c)
{
 func(a,b,c);
 func(a,b,c);
}



Код

    .file    "t.c"
    .text
.globl _tst
    .def    _tst;    .scl    2;    .type    32;    .endef
_tst:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    movl    16(%ebp), %eax
    movl    %eax, 8(%esp)
    movl    12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    _func@12

; <<<<<<<<<<<<<
    subl    $12, %esp
    movl    16(%ebp), %eax
    movl    %eax, 8(%esp)
    movl    12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    _func@12
    subl    $12, %esp
; >>>>>>>>>>>>>

    leave
    ret
    .def    _func@12;    .scl    2;    .type    32;    .endef


Помечен 2й вызов func, первая же комманда subl $12, %esp  резервирует место в стеке (непосредственно в месте вызова)

Добавлено @ 14:32
Хотя, присмтрелся внимательно - это не резервирование места, а восстановление места (стека), которое сбросит __stdcall функция.

Но сути это не меняет - стек можно двигать в процессе работы функции, т.е. вариант с push должен работать


Это сообщение отредактировал(а) xvr - 15.1.2012, 14:33
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1541 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.