Функция обертки в C с использованием структуры указателей на функции - PullRequest
0 голосов
/ 29 августа 2011

Я должен написать код на C, где пользователь должен иметь гибкость в выборе любой существующей БД, записи в файлы или реализации собственного механизма хранения. Мне нужны функции-оболочки, которые перенаправляют на нужные функции, соответствующие механизму хранения, выбранному во время выполнения или компиляции. Скажем, мои варианты хранения - FLATFILE и SQLDB, а моя функция-обертка - insert (значение) . Поэтому, если я выберу FLATFILE в качестве хранилища, при вызове функции-оболочки insert (значение) она должна в свою очередь вызвать функцию, которая записывает в файл. Если я выберу SQLDB, insert (значение) должно вызвать функцию, которая вставляет значения в базу данных.

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

Кто-нибудь знает какие-либо документы, ссылки, примеры и т. Д., На которые я мог бы сослаться, чтобы понять и реализовать нечто подобное? Любые указатели будут оценены. Спасибо!

Спасибо!

Ответы [ 2 ]

1 голос
/ 30 августа 2011
#define BACKEND_FLATFILE 0
#define BACKEND_SQLDB    1

void insert_flatfile(const t_value *v) {
    ...
}

void insert_sqldb(const t_value *v) {
    ...
}

void (*insert_functions[]) (const t_value *) = {
    insert_flatfile, 
    insert_sqldb,
};

void insert_wrapper(t_value *v, int backend) {
    insert_functions[backend](v);
}

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

0 голосов
/ 30 августа 2011

Вы можете использовать простую версию, такую ​​как:

struct backend {
   int (*insert)(...);
   int (*remove)(...);
   ...
};

static struct backend db_backend = { db_insert, db_remove, ... };
static struct backend other_backend = { other_insert, other_remove, ... };

const struct backend *get_backend(enum backend_type type)
{
  switch (type)
  {
     case DB_BACKEND:
       return &db_backend;
     case DB_OTHER:
       return &db_other;
     ...
  }
}

Все вышеперечисленное может быть скрыто в файле C, с get_backend и перечислением общедоступным.Затем вы можете использовать его следующим образом:

struct backend *b = get_backend(DB_BACKEND);
b->insert(...);
b->remove(...);

Многие детали, конечно, отсутствуют (многим нравится, например, typedef).Это базовая настройка, вы также можете создавать функции-оболочки, если вам не нравится синтаксис b->insert(...) или если вы хотите установить бэкэнд один раз, а затем использовать insert() и remove() в коде.Это также полезно, если у вас уже есть какой-то код, который вызывает insert() напрямую, и вы хотите направить вызов на правый задний конец.

Если вы хотите более сложное решение, взгляните на http://www.cs.rit.edu/~ats/books/ooc.pdf. Вам не нужно реализовывать все до мелочей, но это может дать вам несколько идей.

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