Отъезд дополнительного using
директивы прекрасен. Существует немного значения в удалении их, но не очень. Например, это входит в мои списки завершения IntelliSense короче, и поэтому легче перейти.
скомпилированные блоки не затронуты посторонним using
директивы.
Иногда я помещал их в #region
и оставляю свернутым; это делает просмотр файла немного более чистым. IMO, это - одно из нескольких хорошего использования #region
.
C - это компилируемый язык. Вы не можете создавать код во время выполнения «на C»; нет специальной поддержки C для отправки инструкций в память и так далее. Конечно, вы можете попробовать просто выделить память, убедившись, что она исполняемая, и выпустить туда необработанный машинный код. Затем вызовите его из C, используя подходящий указатель на функцию.
Вы не получите никакой помощи от самого языка, это похоже на создание кода и его вызов на BASIC на старой 8-битной машине.
Вы должны быть знакомы с некоторым языком программирования, который поддерживает механизм закрытия, не так ли? К сожалению, 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, ваш код будет простым и независимым от машины.
Если не удалось (функция и применение написаны не вами), попробуйте убедить его изменить свой код.
В случае неудачи у вас нет другого выбора, кроме как использовать некоторые закрывающие библиотеки.
Один из способов сделать это: напишите стандартный файл C с набором нужных вам функций, скомпилируйте его с помощью gcc и загрузите как динамическую библиотеку, чтобы получить указатели на функции.
В конечном итоге, вероятно, было бы лучше, если бы вы могли указать свои функции без необходимости определять их "на лету" (например, с помощью общей шаблонной функции, которая принимает аргументы, определяющие ее конкретное поведение).
Использование 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, но я помню, что работает примерно так.)
Если вы хотите писать код на лету для выполнения, nanojit может быть хорошим решением.
В приведенном выше коде вы пытаетесь создать закрытие. C этого не поддерживает. Есть несколько отвратительных способов подделать это, но из коробки вы не сможете привязать переменную к вашей функции во время выполнения.
Как раскрутка уже упоминалось, «создание кода во время выполнения» не поддерживается языком и потребует много работы.
Я сам не использовал его, но один из моих коллег клянется Lua, " встроенный язык ". Существует Lua C API , который (теоретически, по крайней мере) позволяют выполнять динамические (по сценарию) операции.
Конечно, обратная сторона - то, что конечному пользователю может потребоваться какое-то обучение в Lua.
Это может быть глупый вопрос, но почему функция должна быть создана в вашем приложении? Аналогичным образом, какое преимущество получает конечный пользователь от генерации самой функции (в отличие от выбора одной или нескольких предопределенных функций, которые вы предоставляете)?
Этот механизм называется отражением, когда код изменяет свое собственное поведение во время выполнения. Java поддерживает api отражения для выполнения этой работы.
Но я думаю, что эта поддержка недоступна в C.
Веб-сайт Sun говорит:
Отражение - это мощно, но не должно использоваться без разбора. Если это можно провести операцию без использования отражения, тогда это предпочтительно избегать его использования. В следующие вопросы следует хранить в помните при доступе к коду через отражение.
Недостатки отражения
Накладные расходы на производительность Потому что отражение включает типы, которые динамически разрешается, некоторые Java оптимизация виртуальной машины не может быть исполненным. Следовательно, рефлексивный операции имеют более низкую производительность чем их неотражающие аналоги, и их следует избегать в разделы кода, которые называются часто в чувствительных к производительности Приложения.
Ограничения безопасности
Для отражения требуется среда выполнения разрешение, которое может отсутствовать при запуске под менеджером безопасности. Это важное соображение для кода, который должен выполняться в ограниченный контекст безопасности, такой как в апплете.
Открытие внутренних компонентов
Поскольку отражение позволяет коду выполнять операции, которые были бы незаконно в неотражающем коде, например как доступ к частным полям и методы, использование отражения может привести к неожиданным побочным эффектам, что может сделать код неисправным и может нарушить переносимость. Светоотражающий код разрушает абстракции и поэтому может изменить поведение с помощью обновления платформы. .
Похоже, вы пришли с другого языка, где вы обычно используете этот тип кода. C не поддерживает это, и хотя вы, конечно, могли бы придумать что-нибудь для динамической генерации кода, очень вероятно, что это не стоит усилий.
Вместо этого вам нужно добавить дополнительный параметр в функцию который ссылается на матрицу, над которой предполагается работать. Скорее всего, это то, что язык, поддерживающий динамические функции, в любом случае будет делать внутри.
Если вам действительно нужно динамически создавать функции, возможно, поможет встроенный интерпретатор C. Я только что поискал в Google "встроенный интерпретатор C" и в результате получил Ch:
http://www.softintegration.com/
Никогда о нем не слышал, поэтому я ничего об этом не знаю, но кажется, стоит взглянуть.