我有一个使用C野牛解析器的C++项目。 C分析器使用函数指针的结构来调用函数,这些函数会在通过bison减少产量时创建正确的AST节点:

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代码中按名称调用它们,因此名称修饰不是问题。对它们进行整形将避免名称冲突,因为某些 Action 被称为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++解决方案。

最佳答案

我没问题。 extern关键字不影响调用约定,仅影响提供给链接器的名称。用C++编写的不是实例方法的函数仍然是__cdecl,带有或不带有外部“C”。此外,只要将createActions()保留在同一源代码文件中,这些函数就不需要外部链接。您可以将它们声明为静态,也可以将它们放在未命名的命名空间中以避免冲突。

关于c++ - 在未命名的命名空间中定义的C回调函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2797390/

10-11 22:36
查看更多