Проверьте PowerGUI, PowerShell GUI и редактор сценариев. Я еще не использую его, но я посмотрел демонстрационные видео и взгляды очень хороший. Кроме того, сайт поддерживает библиотеку с демонстрационными сценариями.
Здесь другая превосходная ссылка PowerShell.
Стандартный подход состоит в том, чтобы каждая вариативная функция сопровождалась принимающим аналогом va_list
(как в printf и vprintf). Вариативная версия просто преобразует ...
в va_list
(с использованием макросов из stdarg.h
) и вызывает его сестру, принимающую va_list, которая выполняет реальную работу.
Может быть интересно попробовать просто передать массив, а затем все равно использовать макрос 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;
}
В зависимости от того, что вы передаете, это может быть размеченный союз, который вам нужен (как намекают в комментариях). Это позволит избежать необходимости в вариативных функциях или массивах 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]);
/* ... */
}
Функции с переменным числом переменных используют соглашение о вызовах, при котором вызывающий объект отвечает за извлечение параметров функции из стека, так что да, это можно делать динамически. Он не стандартизирован в 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.