Динамично создающие функции в C

Отъезд дополнительного using директивы прекрасен. Существует немного значения в удалении их, но не очень. Например, это входит в мои списки завершения IntelliSense короче, и поэтому легче перейти.

скомпилированные блоки не затронуты посторонним using директивы.

Иногда я помещал их в #region и оставляю свернутым; это делает просмотр файла немного более чистым. IMO, это - одно из нескольких хорошего использования #region.

14
задан Unheilig 1 May 2015 в 06:36
поделиться

9 ответов

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

Вы не получите никакой помощи от самого языка, это похоже на создание кода и его вызов на BASIC на старой 8-битной машине.

21
ответ дан 1 December 2019 в 06:16
поделиться

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

Вы могли бы найти несколько полезных библиотек, которые имитируют замыкание в C, если бы вы настояли на закрытии. Но большинство этих библиотек сложны и зависят от машины.
В качестве альтернативы, вы можете передумать и согласиться с закрытием в стиле C , если вы можете изменить подпись double () (unsigned, unsigned); .

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

// first, add one extra parameter in the signature of function.
typedef double(function)(double extra, unsigned int,unsigned int);

// second, add one extra parameter in the signature of apply
void apply(double* matrix,unsigned width,unsigned height, function* f, double extra)
{
        for (unsigned y=0; y< height; ++y)
            for (unsigned x=0; x< width ++x)
                    matrix[ y*width + x ] = f(x, y, extra);
        // apply will passing extra to f
}

// third, in constant_function, we could get the context: double extra, and return it
double constant_function(double value, unsigned x,unsigned y) { return value; }

void test(void)
{
        double* matrix = get_a_matrix();
        // fourth, passing the extra parameter to apply
        apply(matrix, w, h, &constant_function, 1212.0);
        // the matrix will be filled with 1212.0
}

Достаточно ли double extra ? Да, но только в этом случае.
Что делать, если требуется больше контекста?
В C параметром общего назначения является void * , мы можем передать любой контекст через один параметр void *, передав адрес контекста.

Вот еще один пример:

typedef double (function)(void* context, int, int );
void apply(double* matrix, int width,int height,function* f,void* context)
{
        for (int y=0; y< height; ++y)
            for (int x=0; x< width ++x)
                    matrix[ y*width + x ] = f(x, y, context); // passing the context
}
double constant_function(void* context,int x,int y)
{
        // this function use an extra double parameter \
        //    and context points to its address
        double* d = context;
        return *d;
}
void test(void)
{
        double* matrix = get_a_matrix();
        double context = 326.0;
        // fill matrix with 326.0
        apply( matrix, w, h, &constant_function, &context);
}

(функция, контекст) пара вроде & constant_function, & context - это замыкание в стиле C .
Каждая функция (F), которая требует закрытия, должна иметь один параметр контекста, который будет передан в закрытие в качестве контекста. И вызывающий F должен использовать правильную пару (f, c).

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

8
ответ дан 1 December 2019 в 06:16
поделиться

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

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

5
ответ дан 1 December 2019 в 06:16
поделиться

Использование FFCALL , которое обрабатывает зависящие от платформы уловки, чтобы заставить эту работу работать:

#include <stdio.h>
#include <stdarg.h>
#include <callback.h>

static double internalDoubleFunction(const double value, ...) {
    return value;
}
double (*constDoubleFunction(const double value))() {
    return alloc_callback(&internalDoubleFunction, value);
}

main() {
    double (*fn)(unsigned int, unsigned int) = constDoubleFunction(5.0);
    printf("%g\n", (*fn)(3, 4));
    free_callback(fn);
    return 0;
}

(Не проверено, поскольку у меня сейчас не установлен FFCALL, но я помню, что работает примерно так.)

5
ответ дан 1 December 2019 в 06:16
поделиться

Если вы хотите писать код на лету для выполнения, nanojit может быть хорошим решением.

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

4
ответ дан 1 December 2019 в 06:16
поделиться

Как раскрутка уже упоминалось, «создание кода во время выполнения» не поддерживается языком и потребует много работы.

Я сам не использовал его, но один из моих коллег клянется Lua, " встроенный язык ". Существует Lua C API , который (теоретически, по крайней мере) позволяют выполнять динамические (по сценарию) операции.

Конечно, обратная сторона - то, что конечному пользователю может потребоваться какое-то обучение в Lua.

Это может быть глупый вопрос, но почему функция должна быть создана в вашем приложении? Аналогичным образом, какое преимущество получает конечный пользователь от генерации самой функции (в отличие от выбора одной или нескольких предопределенных функций, которые вы предоставляете)?

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

Этот механизм называется отражением, когда код изменяет свое собственное поведение во время выполнения. Java поддерживает api отражения для выполнения этой работы.
Но я думаю, что эта поддержка недоступна в C.

Веб-сайт Sun говорит:

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

Недостатки отражения

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

Ограничения безопасности

Для отражения требуется среда выполнения разрешение, которое может отсутствовать при запуске под менеджером безопасности. Это важное соображение для кода, который должен выполняться в ограниченный контекст безопасности, такой как в апплете.

Открытие внутренних компонентов

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

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

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

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

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

Если вам действительно нужно динамически создавать функции, возможно, поможет встроенный интерпретатор C. Я только что поискал в Google "встроенный интерпретатор C" и в результате получил Ch:

http://www.softintegration.com/

Никогда о нем не слышал, поэтому я ничего об этом не знаю, но кажется, стоит взглянуть.

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

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