8

我曾经使用 OpenC++ ( http://opencxx.sourceforge.net/opencxx/html/overview.html ) 来执行代码生成,例如:

资源:

class MyKeyword A {
  public:
    void myMethod(inarg double x, inarg const std::vector<int>& y, outarg double& z);
};

生成:

class A {
  public:
    void myMethod(const string& x, double& y);
    // generated method below:
    void _myMehtod(const string& serializedInput, string& serializedOutput) {
      double x;
      std::vector<int> y;
      // deserialized x and y from serializedInput
      double z;
      myMethod(x, y, z);
    }
};

这种代码生成直接匹配OpenC++教程(http://www.csg.is.titech.ac.jp/~chiba/opencxx/tutorial.pdf)中的用例,通过编写元级程序进行处理“MyKeyword”、“inarg”和“outarg”并执行代码生成。但是,OpenC++ 现在有点过时且不活跃,我的代码生成器只能在 g++ 3.2 上运行,并且在解析更高版本的 g++ 头文件时会触发错误。

我看过 VivaCore,但它没有提供编译元级程序的基础结构。我也在看 LLVM,但我找不到指导我解决源到源编译用法的文档。我也知道 ROSE 编译器框架,但我不确定它是否适合我的使用,以及它的专有 C++ 前端二进制文件是否可以在商业产品中使用,以及是否有 Windows 版本可用。

非常感谢任何对特定教程/论文/文档的评论和指针。

4

3 回答 3

3

我不知道任何现成的解决方案,但您可以用相对较少的努力构建自己的解决方案。一种可能的选择是 Elsa C++ 解析器,它有点过时,但易于使用且可扩展。另一种选择是篡改由 Clang++ 生成的 XML AST。我在不同的场景中使用了这两种方法。

于 2010-05-24T15:35:30.447 回答
0

你知道模板元编程的做法吗?如果您以前没有使用过它,它是 C++ 预处理器的应用程序,用于创建奇怪的元程序,感觉更像 LISP 而不是 C++。这个想法和上面的一样——有一个预编译步骤,根据某些输入生成重复的代码。但是,它都是在编译时执行的(而 OpenC++ 看起来在运行时做了几件事)。

考虑到看起来你无论如何都愿意学习一门新的,你愿意用它作为替代“语言”吗?

Boost 提供了一个库,它使用这种技术来提供简单的序列化,就像你上面展示的那样。 从其手册中的教程

/////////////////////////////////////////////////////////////
// gps coordinate
//
// illustrates serialization for a simple type
//
class gps_position
{
private:
    friend class boost::serialization::access;
    // When the class Archive corresponds to an output archive, the
    // & operator is defined similar to <<.  Likewise, when the class Archive
    // is a type of input archive the & operator is defined similar to >>.
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;
public:
    gps_position(){};
    gps_position(int d, int m, float s) :
        degrees(d), minutes(m), seconds(s)
    {}
};

int main() {
    // create and open a character archive for output
    std::ofstream ofs("filename");

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    {
        boost::archive::text_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
        // archive and stream closed when destructors are called
    }

    // ... some time later restore the class instance to its orginal state
    gps_position newg;
    {
        // create and open an archive for input
        std::ifstream ifs("filename");
        boost::archive::text_iarchive ia(ifs);
        // read class state from archive
        ia >> newg;
        // archive and stream closed when destructors are called
    }
    return 0;
}
于 2010-05-24T07:07:55.690 回答
0

您可以考虑我们的DMS 软件再造工具包。DMS 是将任意语言的源文本解析为编译器数据结构(AST、符号表、控制流图、数据流图,具体取决于您采用多远)的通用基础。

DMS 是一个通用的源到源程序转换系统。您可以应用源到源的模式导向转换,或编写过程转换(很像 OpenC++),然后重新生成与转换后的程序相对应的可编译源文本。

DMS 由显式语言定义参数化,并处理 C、C#、COBOL、Java、Python、javascript、Fortran。

它有一个完整的C++ 前端,可以处理许多真正的 C++ 方言(ANSI、GNU、MS),具有全名和类型解析。带有 C++ 前端的 DMS 可以在多个编译单元内和跨多个编译单元执行由“元程序”控制的转换。它被愤怒地用于对 C++ 软件系统进行彻底重组,包括大规模重新构建任务航空电子软件(参见网站上的论文),最终用于无人机。

DMS 在 Windows 上运行,并且在使用 sh 脚本的 Wine 下透明地在 Linux 上运行。

编辑 2/3/2011:DMS 在 Linux 和 Solaris 上的 Wine 下似乎也运行良好。在 OSX 下对 Wine 上的 DMS 进行测试。

编辑 3/1/2011:DMS 似乎也在 Wine for OSX 下运行。

编辑 2/21/2013:C++ 前端现在处理 ANSI C++11,以及 C++11 的 MS 和 GNU 版本。

编辑 2/24/2015:现在处理 ANSI、MS 和 GNU 风格的 C++14。

编辑 1/16/2019:现在处理 ANSI、MS 和 GNU 风格的 C++17。

于 2010-05-26T02:25:17.423 回答