Передающие параметры динамично к функциям variadic

Проверьте PowerGUI, PowerShell GUI и редактор сценариев. Я еще не использую его, но я посмотрел демонстрационные видео и взгляды очень хороший. Кроме того, сайт поддерживает библиотеку с демонстрационными сценариями.

Здесь другая превосходная ссылка PowerShell.

5
задан Matt Joiner 12 November 2009 в 14:11
поделиться

4 ответа

Стандартный подход состоит в том, чтобы каждая вариативная функция сопровождалась принимающим аналогом va_list (как в printf и vprintf). Вариативная версия просто преобразует ... в va_list (с использованием макросов из stdarg.h ) и вызывает его сестру, принимающую va_list, которая выполняет реальную работу.

2
ответ дан 18 December 2019 в 13:15
поделиться

Может быть интересно попробовать просто передать массив, а затем все равно использовать макрос vararg. В зависимости от выравнивания стека, это может быть Just Work (tm).

Это, вероятно, не оптимальное решение, я в основном опубликовал его, потому что нашел идею интересной. После тестирования этот подход работал на моем Linux x86, но не на x86-64 - его, вероятно, можно улучшить. Этот метод будет зависеть от выравнивания стека, выравнивания структуры и, возможно, многого другого.

void varprint(int count, ...)
{
    va_list ap;
    int32_t i;

    va_start(ap, count);
    while(count-- ) {
        i = va_arg(ap, int32_t);
        printf("Argument: %d\n", i);
    }
    va_end(ap); 
}

struct intstack
{
    int32_t pos[99];
};

int main(int argc, char** argv)
{
    struct intstack *args = malloc(sizeof(struct intstack));
    args->pos[0] = 1;
    args->pos[1] = 2;
    args->pos[2] = 3;
    args->pos[3] = 4;
    args->pos[4] = 5;

    varprint(5, *args);
    return 0;
}
1
ответ дан 18 December 2019 в 13:15
поделиться

В зависимости от того, что вы передаете, это может быть размеченный союз, который вам нужен (как намекают в комментариях). Это позволит избежать необходимости в вариативных функциях или массивах void * и ответит на вопрос « как some_function знает, что вы на самом деле передали ». У вас может быть примерно такой код:

enum thing_code { INTEGER, DOUBLE, LONG };

struct thing
{
 enum thing_code code;
 union
 {
    int a;
    double b;
    long c;
 };
};

void some_function(size_t n_things, struct thing *things)
{
    /* ... for each thing ... */
    switch(things[i].code)
    {
      case INTEGER:
      /* ... */
    }
}

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

struct thing
{
 void (*print)(struct thing*);
 union
 {
   ...
 };
}

void some_function(size_t n_things, struct thing *things)
{
  /* .. for each thing .. */
  things[i]->print(things[i]);
  /* ... */
}
0
ответ дан 18 December 2019 в 13:15
поделиться

Функции с переменным числом переменных используют соглашение о вызовах, при котором вызывающий объект отвечает за извлечение параметров функции из стека, так что да, это можно делать динамически. Он не стандартизирован в C и обычно требует некоторой сборки, чтобы вручную ввести желаемые параметры и правильно вызвать вариативную функцию.

Соглашение о вызовах cdecl требует, чтобы аргументы были помещены в правильном порядке, и после вызова байты, переданные в качестве аргументов перед вызовом, выталкиваются. Таким образом, вызываемая функция может получать произвольное количество параметров, поскольку вызывающий будет обрабатывать возврат указателя стека в состояние до вызова. Место, занимаемое аргументами перед ... безопасная нижняя граница для количества перемещаемых байтов. Дополнительные аргументы с переменным числом аргументов интерпретируются во время выполнения.

FFCALL - это библиотека, которая предоставляет оболочки для динамической передачи параметров функциям с переменным числом аргументов. Вас интересует группа функций avcall . Вот пример вызова функций, которые вы указали выше:

#include <avcall.h>

av_alist argList;
int retVal;
av_start_int(argList, some_function, retval);
av_int(argList, a);
av_int(argList, b);
av_type(argList, val1);
...
av_type(argList, valn);
av_call(argList);

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

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

FFCALL - это библиотека, которая предоставляет оболочки для динамической передачи параметров функциям с переменным числом аргументов. Вас интересует группа функций avcall . Вот пример вызова функций, которые вы указали выше:

#include <avcall.h>

av_alist argList;
int retVal;
av_start_int(argList, some_function, retval);
av_int(argList, a);
av_int(argList, b);
av_type(argList, val1);
...
av_type(argList, valn);
av_call(argList);

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

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

FFCALL - это библиотека, которая предоставляет оболочки для динамической передачи параметров функциям с переменным числом аргументов. Вас интересует группа функций avcall . Вот пример вызова функций, которые вы указали выше:

#include <avcall.h>

av_alist argList;
int retVal;
av_start_int(argList, some_function, retval);
av_int(argList, a);
av_int(argList, b);
av_type(argList, val1);
...
av_type(argList, valn);
av_call(argList);

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

11
ответ дан 18 December 2019 в 13:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: