WedX - журнал о программировании и компьютерных науках

Функции обратного вызова C, определенные в безымянном пространстве имен?

У меня есть проект C++, в котором используется парсер C bison. Синтаксический анализатор C использует структуру указателей функций для вызова функций, которые создают правильные узлы AST, когда производство сокращается с помощью bison:

typedef void Node;
struct Actions {
  Node *(*newIntLit)(int val);
  Node *(*newAsgnExpr)(Node *left, Node *right);
  /* ... */
};

Теперь, в части проекта C++, я заполняю эти указатели

class AstNode {
  /* ... */
};
class IntLit : public AstNode { 
  /* ... */
};

extern "C" {
  Node *newIntLit(int val) {
    return (Node*)new IntLit(val);
  }

  /* ... */
}

Actions createActions() {
  Actions a;
  a.newIntLit = &newIntLit;
  /* ... */
  return a;
}

Теперь единственная причина, по которой я помещаю их в extern "C", заключается в том, что я хочу, чтобы у них были соглашения о вызовах C. Но в идеале я бы хотел, чтобы их имена все еще были искажены. Они никогда не вызываются по имени из кода C, поэтому искажение имен не является проблемой. Их искажение позволит избежать конфликтов имен, поскольку некоторые действия вызываются как error, а функция обратного вызова C++ имеет уродливые имена, подобные приведенным ниже, только для того, чтобы избежать конфликтов имен с другими модулями.

extern "C" {
  void uglyNameError(char const *str) {
    /* ... */
  }

  /* ... */
}

a.error = &uglyNameError;

Я задавался вопросом, возможно ли это, просто задав функцию связи типа C

extern "C" void fty(char const *str);
namespace {
  fty error; /* Declared! But i can i define it with that type!? */
}

Любые идеи? Я ищу решения Standard-C++.


  • Не можете ли вы скомпилировать вывод Bison в виде кода C++, полностью избежав проблемы? 09.05.2010
  • @Konrad, мой коллега, сказал, что с режимом bison C ++ неудобно работать, поэтому мы делаем эту часть с чистым C и абстрагируем его, поэтому вместе со сканером составляет чистую библиотеку C. 09.05.2010

Ответы:


1

Я не понимаю проблемы. Ключевое слово extern не влияет на соглашение о вызовах, а только на имя, представляемое компоновщику. Функция, написанная на C++, которая не является методом экземпляра, по-прежнему называется __cdecl, с внешним "C" или без него. Кроме того, пока вы храните createActions() в одном и том же файле исходного кода, эти функции не нуждаются во внешней компоновке. Вы можете объявить их статическими или поместить в безымянное пространство имен, чтобы избежать конфликтов.

09.05.2010
  • Ах, тогда я мог бы сделать static. Хорошая идея, почему я об этом не подумал :) Я думал только о безымянных пространствах имен, но это ничего не сделает с их связью и не предотвратит конфликты для extern "C" функций. Но static действительно может сработать! Что касается остальных частей вашего ответа: это может иметь значение для соглашения о вызовах, если реализация этого хочет. Я хотел не зависеть от какой-либо конкретной реализации, поэтому сделал их extern "C". 09.05.2010
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]