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