如何避免C ++和boost :: python文档之间的冗余? [英] How to avoid redundancy between c++ and boost::python docs?

查看:79
本文介绍了如何避免C ++和boost :: python文档之间的冗余?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用boost :: python在c ++代码中添加一个python模块.用doxygen记录了c ++项目. 我想为python模块创建一个文档,但是我不知道如何不像这样多余:

I'm adding a python module in a c++ code, using boost::python. The c++ project is documented with doxygen. I want to create a documentation for the python module but I don't know how not to be redundant like this :

#include <boost/python.hpp>
using namespace boost::python;

/** @brief Sum two integers
  * @param a an integer
  * @param b another integer
  * @return sum of integers
  */
int sum(int a, int b)
{
    return a+b;
}

BOOST_PYTHON_MODULE(pymodule)
{ 
    def("sum",&sum,args("a","b"),
        "Sum two integers.\n\n:param a: an integer\n:param b: another integer\n:returns: sum of integers");
};

我在docstring和doxygen注释中说了同样的话.有什么想法吗?

Here I say the same thing in docstring and doxygen comments. Any ideas ?

编辑:c ++文档不是公开的,而python接口是c ++的子集.

The c++ doc isn't public and the python interface is a subset of c++.

推荐答案

我是代码生成的爱好者,我认为这是部署它的合理情况.

I'm a fan of code generation and I believe that this is a reasonable situation to deploy it.

如果您在编写Doxygen DocStrings方面有一定的纪律性,并且避免在其中编写复杂的标记,那么编写一个小型解析器来提取它们并将它们替换回Python DocStrings中就不那么困难了.

If you're a bit disciplined in writing your Doxygen DocStrings and refrain from complicated markup in them, it is not that hard to write a small parser that extracts them and substitutes them back into the Python DocStrings.

这是一个小例子.它没有足够的功能来处理任何实际的用例,但我相信,除非您只有一手完整的功能来进行文档记录,否则对其进行扩展并不困难且值得付出努力.

Here is a small example. It won't be powerful enough to handle any realistic use-case but I believe that extending it would not be hard and worth the effort unless you only have a hand-full of functions to document.

在每个Doxygen DocString之前放置一个特殊注释,该注释为以下注释块命名.在这里,我正在使用语法

Place a special comment before each Doxygen DocString that gives the following comment block a name. Here, I'm using the syntax

// DocString: sum
/**
 * @brief Sum two integers
 * @param a an integer
 * @param b another integer
 * @return sum of integers
 *
 */
int sum(int a, int b);

将名称sum与以下DocString关联.

to associate the name sum with the following DocString.

然后,在引用该名称的Python绑定中放置另一个特殊字符串.我在这里使用以下语法.

Then, place another special string inside the Python bindings that references that name. I'm using the following syntax here.

BOOST_PYTHON_MODULE(pymodule)
{ 
  def("sum",&sum,args("a","b"), "@DocString(sum)");
};

现在,我们需要一个工具来提取Doxygen DocString并将其替换为Python绑定.

Now we need a tool to extract the Doxygen DocStrings and substitutes them into the Python bindings.

我已经说过,这个示例是人为设计的,但它应该说明这个想法,并证明这样做并不难.

As I've said, this example is contrived but it should show the idea and demonstrate that it is not too hard to do.

import re
import sys

def parse_doc_string(istr):
    pattern = re.compile(r'@(\w+)\s+(.*)')
    docstring = list()
    for line in map(lambda s : s.strip(), istr):
        if line == '/**':
            continue
        if line == '*/':
            return docstring
        line = line.lstrip('* ')
        match = pattern.match(line)
        if match:
            docstring.append((match.group(1), match.group(2)))

def extract(istr, docstrings):
    pattern = re.compile(r'^//\s*DocString:\s*(\w+)$')
    for line in map(lambda s : s.strip(), istr):
        match = pattern.match(line)
        if match:
            token = match.group(1)
            docstrings[token] = parse_doc_string(istr)

def format_doc_string(docstring):
    return '\n'.join('{}: {}'.format(k, v) for (k, v) in docstring)

def escape(string):
    return string.replace('\n', r'\n')

def substitute(istr, ostr, docstrings):
    pattern = re.compile(r'@DocString\((\w+)\)')
    for line in map(lambda s : s.rstrip(), istr):
        for match in pattern.finditer(line):
            token = match.group(1)
            docstring = format_doc_string(docstrings[token])
            line = line.replace(match.group(0), escape(docstring))
        print(line, file=ostr)

if __name__ == '__main__':
    sourcefile = sys.argv[1]
    docstrings = dict()
    with open(sourcefile) as istr:
        extract(istr, docstrings)
    with open(sourcefile) as istr:
        with sys.stdout as ostr:
            substitute(istr, ostr, docstrings)

在源文件上运行此脚本会产生以下输出.

Running this script over the source file produces the following output.

#include <boost/python.hpp>
using namespace boost::python;

// DocString: sum
/**
 * @brief Sum two integers
 * @param a an integer
 * @param b another integer
 * @return sum of integers
 *
 */
int sum(int a, int b)
{
  return a+b;
}

BOOST_PYTHON_MODULE(pymodule)
{
  def("sum",&sum,args("a","b"), "brief: Sum two integers\nparam: a an integer\nparam: b another integer\nreturn: sum of integers");
};

在脚本上加上两个小时的修饰,就可以了.

Add two hours of polishing to the script and you're good to go.

由于这也可能引起其他人的兴趣,如果有人已经编写了这样的脚本,我也不会感到惊讶.如果不是这样,将您的软件发布为免费软件肯定会受到其他人的欢迎.

Since this is likely to be of interest to other people as well, I wouldn't be surprised if somebody had already written such a script. And if not, publishing yours as free software would certainly be welcomed by others.

这篇关于如何避免C ++和boost :: python文档之间的冗余?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆