Как позволить пользователю создать функцию?[библиотека?] - PullRequest
2 голосов
/ 10 марта 2011

Существует ли какая-либо бесплатная библиотека, позволяющая пользователю легко создавать математическое выражение на языке C, которое можно использовать как любую другую функцию?Я имею в виду c выражение / функцию, которая может быть такой же быстрой, как «встроенное» математическое выражение и может много раз использоваться в программе.Я думаю, что я могу как-то сделать на C, но кто-нибудь может сказать, может ли это быть реально, если это должна быть функция CUDA dveice?

Ответы [ 2 ]

2 голосов
/ 10 марта 2011

libtcc (от TCC ) может использоваться как очень маленький и быстрый JIT;см. libtcc_test.cc для примера использования.

2 голосов
/ 10 марта 2011

Есть несколько вариантов.Я предполагаю, что вы хотите что-то, что пользователь может «вызвать» несколько раз, например:

void *s = make_func("2 * x + 7");
...
printf("%lf\n", call_func(s, 3.0)); // prints 13
...
printf("%lf\n", call_func(s, 5.0)); // prints 17
...
free_func(s);

Один из вариантов - реализовать это как рекурсивную структуру, содержащую указатели и константы функций.Что-то вроде:

enum item_type { VAR, CONST, FUNC };

struct var {
  enum item_type;
  int id;
};

struct constant {
  enum item_type;
  double value;
};

struct func {
  enum item_type;
  double (*func)(double, double);
  enum item_type *a, *b;
};

Тогда make_func будет анализировать приведенную выше строку во что-то вроде:

(struct func *){ FUNC, &plus,
  (struct func *){ FUNC, &times,
    (struct constant *){ CONST, 2 },
    (struct var *){ VAR, 'x' } }
  (struct constant *){ CONST, 7 } }

Если вы понимаете, что - enum type_item в struct funcиспользуется для указания на следующий узел в дереве (точнее, на первый элемент этого узла, который является enum), а enum - это то, что наш код использует, чтобы выяснить, какой тип элемента.Затем, когда мы используем функцию call(void *, ...), она подсчитывает, сколько существует переменных - это количество дополнительных аргументов, которые должна быть передана функции call, - затем заменяет переменные значениями, с которыми мы ее вызвали, затемвыполняет вычисления.

Другой вариант (который, вероятно, будет значительно быстрее и проще в расширении) - это использовать что-то вроде libjit , чтобы выполнить большую часть этой работы за вас.Я никогда не использовал его, но JIT-компилятор дает вам некоторые базовые строительные блоки (такие как «сложение», «умножение» и т. Д. «Инструкции»), которые вы можете связывать вместе по мере необходимости, и он компилирует их в фактический код сборки (поэтомуне нужно проходить через построенное синтаксическое дерево, вызывающее указатели на функции, как это было раньше), поэтому, когда вы вызываете его, он настолько быстр и динамичен, насколько это возможно.

Я не знаю API libjit, но он выглядит легко способнымделать то, что вам нужно.make_func и free_func могут быть почти такими же, как они указаны выше (вам, возможно, придется изменить свои вызовы на call_func), и в основном будут создавать, использовать и уничтожать объект JIT на основе того, как он анализируетстрока пользователя.На самом деле то же самое, что и выше, но вам не нужно определять синтаксическое дерево, типы данных и т. Д. Самостоятельно.

Надеюсь, это несколько полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...