Вызывание функции C с varargs аргументом динамично

Если вы мигрировали, а затем отредактируйте его, тогда Laravel не поднимет новый столбец.

Вы должны перенести свежие и посевные семена снова:

php artisan migrate:fresh --seed (не делайте этого в производстве)

15
задан Randakar 12 November 2008 в 09:30
поделиться

9 ответов

В CamelBones я использую libffi для вызова objc_msgSend (), который является функцией varargs. Работы обработка.

9
ответ дан 1 December 2019 в 02:29
поделиться

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

архитектура безопасный способ сделать это должно использовать va_list макросы (что n-alexander упомянул), иначе можно столкнуться с проблемами с тем, как различные типы данных дополнены в памяти.

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

самые стандартные функции IO имеют varargs версии: vprintf для printf, vsprintf для sprintf... Вы получаете идею. Посмотрите, реализует ли Ваша библиотека функцию, названную "vweb_submit_data" или чем-то к тому эффекту. Если они не делают, пошлите им по электронной почте и скажите им фиксировать свою библиотеку.

3 000 строк того же самого (даже если это - вызванный препроцессор) заставляет меня съежиться

9
ответ дан 1 December 2019 в 02:29
поделиться

Можно ли реструктурировать код так, чтобы это не было необходимо? Возможно, Вы могли взять входящий буфер и сделать его более детерминированным:

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);

}

Жаль это не могло быть более изложено в деталях - моя жена призвала меня на завтрак. :-)

1
ответ дан 1 December 2019 в 02:29
поделиться

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

2
ответ дан 1 December 2019 в 02:29
поделиться

Примечание: код уже зависим от компилятора (хотя, возможно, не зависимый от процессора), потому что вызов web_submit_data предполагает там, что подвыражения аргумента в вызове процедуры оценены слева направо, порядок, но язык C оставляет порядок оценки аргумента неуказанным.

Видят ссылку: http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value

Поэтому, возможно, непортативное решение не собирается делать вещи значительно хуже для Вас.

1
ответ дан 1 December 2019 в 02:29
поделиться

Запишите это однажды с препроцессором и никогда не оглядывайтесь назад.

#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 */
1
ответ дан 1 December 2019 в 02:29
поделиться

Обратите внимание, что пример кода, который Вы отправили, имеет неопределенное поведение - запятые, что параметры отдельной функции не являются точками последовательности (те запятые не являются оператором запятой), таким образом изменяя i и или j многократно в результатах списка аргументов вызова функции в неопределенном поведении.

Это - то, не говоря уже о том, что порядок оценки аргументов вызова функции не указан стандартом - поэтому, даже если бы Вы сделали модификацию i, и j функции использования для оценки аргументов (сами вызовы функции являются точками последовательности), то Вы в значительной степени передали бы указатели в неопределенном порядке.

кроме того, я не вижу, как web_submit_data() знает, сколько аргументов это было передано - я не вижу количества или категорического аргумента сигнальной метки в конце. Но я предполагаю, что Ваш пример может быть просто, что - пример, который не мог бы иметь полных, точных деталей. С другой стороны, это web_submit_data() проблема так или иначе, правильно?

1
ответ дан 1 December 2019 в 02:29
поделиться

Так как это обычно - не проблема для передачи [еще 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). Так используйте эту технику на Ваш собственный риск, и проверьте, проверьте, проверьте).

3
ответ дан 1 December 2019 в 02:29
поделиться

Существует два способа передать переменное количество аргументов: к функции, которая принимает "..." или к функции, которая принимает va_list.

Вы не можете динамично определить количество аргументов в пользу "..." интерфейс, но необходимо смочь сделать так для va_list один. Google для va_start, va_end, и va_list.

1
ответ дан 1 December 2019 в 02:29
поделиться
Другие вопросы по тегам:

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