Если вы мигрировали, а затем отредактируйте его, тогда Laravel не поднимет новый столбец.
Вы должны перенести свежие и посевные семена снова:
php artisan migrate:fresh --seed
(не делайте этого в производстве)
В CamelBones я использую libffi для вызова objc_msgSend (), который является функцией varargs. Работы обработка.
Аргументами переменной длины является в основном просто указатель на набор упакованных данных, которые передаются необходимой функции. Это - обязанность вызванной функции интерпретировать эти упакованные данные.
архитектура безопасный способ сделать это должно использовать va_list макросы (что n-alexander упомянул), иначе можно столкнуться с проблемами с тем, как различные типы данных дополнены в памяти.
надлежащий способ разработать функции varargs состоит в том, чтобы на самом деле иметь две версии, та, которая принимает '...', который в свою очередь извлекает va_list и передает его функции, которая берет va_list. Таким образом, можно динамично создать аргументы, если Вы должны и можете вместо этого назвать va_list версию функции.
самые стандартные функции IO имеют varargs версии: vprintf для printf, vsprintf для sprintf... Вы получаете идею. Посмотрите, реализует ли Ваша библиотека функцию, названную "vweb_submit_data" или чем-то к тому эффекту. Если они не делают, пошлите им по электронной почте и скажите им фиксировать свою библиотеку.
3 000 строк того же самого (даже если это - вызванный препроцессор) заставляет меня съежиться
Можно ли реструктурировать код так, чтобы это не было необходимо? Возможно, Вы могли взять входящий буфер и сделать его более детерминированным:
struct form_field
{
char[FIELD_NAME_MAX] name;
char[FIELD_VALUE_MAX] val;
};
web_submit_data_buffer_gazillion_items( const char *bufferName, const char *bufferValue)
{
/*
loop over bufferName somehow, either with a known size or terminating record,
and build an array of form_field records
*/
//loop
{
// build array of records
}
web_submit_data(record_array, array_len);
}
Жаль это не могло быть более изложено в деталях - моя жена призвала меня на завтрак. :-)
Нет никакого портативного способа создать список аргументов для функции аргумента переменной в C во время выполнения. Существуют несколько зависящие от реализации приемы там, dyncall библиотека, которую Вы нашли, похожа на хороший и вероятно более портативный, чем большинство.
Примечание: код уже зависим от компилятора (хотя, возможно, не зависимый от процессора), потому что вызов web_submit_data
предполагает там, что подвыражения аргумента в вызове процедуры оценены слева направо, порядок, но язык C оставляет порядок оценки аргумента неуказанным.
Видят ссылку: http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value
Поэтому, возможно, непортативное решение не собирается делать вещи значительно хуже для Вас.
Запишите это однажды с препроцессором и никогда не оглядывайтесь назад.
#define WEB_SUBMIT_BUFFER(name, val) \
do { \
const int size = 129; \
int i = 0; \
int j = 11; \
web_submit_data(&(name)[i++ * size], \
&(name)[i++ * size], \
/* etc ad nauseum */ \
} while (0)
Или если количество аргументов фиксируется для каждого определенного вызова, запишите, что сценарий для генерации препроцессора определяет, чтобы скрыться, как отвратительный, который вызов.
#define WEB_SUBMIT_BUFFER_32(name, val) \
do { \
const int size = 129; \
int i = 0; \
int j = 11; \
web_submit_data(&(name)[i++ * size], \
&(name)[i++ * size], \
/* 32 times */ \
} while (0)
#define WEB_SUBMIT_BUFFER_33(name, val) ...
#define WEB_SUBMIT_BUFFER_34(name, val) /* etc */
Обратите внимание, что пример кода, который Вы отправили, имеет неопределенное поведение - запятые, что параметры отдельной функции не являются точками последовательности (те запятые не являются оператором запятой), таким образом изменяя i
и или j
многократно в результатах списка аргументов вызова функции в неопределенном поведении.
Это - то, не говоря уже о том, что порядок оценки аргументов вызова функции не указан стандартом - поэтому, даже если бы Вы сделали модификацию i
, и j
функции использования для оценки аргументов (сами вызовы функции являются точками последовательности), то Вы в значительной степени передали бы указатели в неопределенном порядке.
кроме того, я не вижу, как web_submit_data()
знает, сколько аргументов это было передано - я не вижу количества или категорического аргумента сигнальной метки в конце. Но я предполагаю, что Ваш пример может быть просто, что - пример, который не мог бы иметь полных, точных деталей. С другой стороны, это web_submit_data()
проблема так или иначе, правильно?
Так как это обычно - не проблема для передачи [еще 113] аргументы функции, берущей аргументы переменной, чем функция ожидает (см. сноску № 1), можно сделать что-то как следующее:
// you didn't give a clear specification of what you want/need, so this
// example may not be quite what you want as I've had to guess at
// some of the specifications. Hopefully the comments will make clear
// what I may have assumed.
//
// NOTE: while I have compiled this example, I have not tested it,
// so there is a distinct possiblity of bugs (particularly
// off-by-one errors). Check me on this stuff, please.
// I made these up so I could compile the example
#define ITEMDATA ((char const*) NULL)
#define ENDITEM ((char const*) 0xffffffff)
void web_submit_data_wrapper( const char*bufferName,
const char* bufferValue,
size_t headerCount, // number of header pointers to pass (8 in your example)
size_t itemStartIndex, // index where items start in the buffers (11 in your example)
size_t itemCount, // number of items to pass (unspecified in your example)
size_t dataSize ) // size of each header or item (129 in your example)
{
// kMaxVarArgs would be 3000 or a gazillion in your case
// size_t const kMaxVarArgs = 20; // I'd prefer to use this in C++
#define kMaxVarArgs (20)
typedef char const* char_ptr_t;
typedef char_ptr_t char_ptr_array_t[kMaxVarArgs];
char_ptr_array_t varargs = {0};
size_t idx = 0;
// build up the array of pararmeters we'll pass to the variable arg list
// first the headers
while (headerCount--) {
varargs[idx++] = &bufferName[idx * dataSize];
}
// mark the end of the header data
varargs[idx++] = ITEMDATA;
// now the "items"
while (itemCount--) {
varargs[idx++] = &bufferName[itemStartIndex * dataSize];
varargs[idx++] = &bufferValue[itemStartIndex * dataSize];
varargs[idx++] = ENDITEM;
++itemStartIndex;
}
// the thing after the last item
// (I'm not sure what this is from your example)
varargs[idx] = &bufferName[itemStartIndex * dataSize];
// now call the target function - the fact that we're passing more arguments
// than necessary should not matter due to the way VA_ARGS are handled
// but see the Footnote in the SO answer for a disclaimer
web_submit_data(
varargs[0],
varargs[1],
varargs[2],
//... ad nasuem until
varargs[kMaxVarArgs-1]
);
}
<час> Сноска № 1: Если Вы думаете о том, как макросы в stdargs.h
действие это становится ясным. Однако я не утверждаю, что эта техника была бы совместимыми стандартами. На самом деле в новейшей истории stackoverflow отвечает, что я отправил где я; ve, сделанные этой правовой оговоркой, как на самом деле находили, были совместимыми нестандартами (обычно когда-либо бдительный litb). Так используйте эту технику на Ваш собственный риск, и проверьте, проверьте, проверьте).
Существует два способа передать переменное количество аргументов: к функции, которая принимает "..." или к функции, которая принимает va_list.
Вы не можете динамично определить количество аргументов в пользу "..." интерфейс, но необходимо смочь сделать так для va_list один. Google для va_start, va_end, и va_list.