2012-12-10 39 views
7

我想生成在头文件中定义的过程的空实现。理想情况下,他们应该为指针返回NULL,为整数等返回0,并且在理想的世界中,还会打印stderr哪个函数被调用。从头文件自动生成C代码

这样做的动机是需要实现一个将复杂的现有API(头文件)的子集调整到另一个库的包装器。 API中只有少数程序需要委派,但尚不清楚哪些程序。所以我希望使用一种迭代方法,在这种情况下,我运行这个自动生成的包装器,查看所谓的内容,使用委托实现它,然后重复。

我看到Automatically generate C++ file from header?但答案似乎是特定于C++。

因此,对于那些需要简单地说明问题的人来说,如何在给定头文件的情况下自动生成这样的实现呢?我更喜欢现有的工具 - 我现在最简单的解决方案就是使用pycparser。

更新谢谢你们。两个好的答案。还张贴我目前的黑客。

+0

现在你还没有真正问过一个问题,据我所知,但我猜你在问一个现有的工具可以做到这一点?不幸的是,我不知道任何工具,但它听起来基本足以做一个快速的python(或任何其他高级语言)实现来解决它? – Jite

+0

我已经澄清了这个问题。是的,我可以写一个程序来做到这一点。但它不是微不足道的 - 例如,它需要一个体面的解析器。头部足够大,并且足够复杂,基于特定正则表达式的kludge将会耗费大量时间。 –

+0

嗨,过程是否需要轻松重复?例如,你是否希望能够在新版本的API发布时更新存根实现? – OlduwanSteve

回答

1

UML建模工具能够以选择的语言生成默认实现。通常还支持导入源代码(包括C头文件)。你可以尝试导入你的头文件并从中生成源代码。我个人有Enterprise Architect的经验,它支持这两种操作。

+0

啊是的,ea可能会这样做(虽然不是打印语句)。虽然也许只有付费版本,并且我还没有许可证多年。将检查出来。谢谢。 –

+0

我相信也有免费的工具,可以做这个东西,要求谷歌 – SomeWittyUsername

+0

它曾经是免费的uml工具吸得非常糟糕(我是一个粉丝,只是没有客户需要uml),但它可能已经改变。将要看。 –

1

警告:这是一个未经研究的答案,因为我自己没有任何经验。

我想你可能会为模拟框架而设计一些单元测试。这样的框架的一个例子是:cmock

项目页面建议它将从头部生成代码。然后你可以拿起代码并调整它。

+0

这是一个有趣的想法,谢谢。我目前正在与cpp作战,只是为了以我想要的格式获得标题,但会更多地考虑这种方法。 –

2

所以,我打算将ea建议标记为“答案”,因为我认为这可能是一般最好的想法。尽管我认为cmock建议在tdd方法中非常有效,在这种方法中,图书馆开发是由测试失败驱动的,我可能最终会尝试这种方式。但现在,我需要一个更快捷+更肮脏的方法,以交互方式工作(所讨论的库是另一个动态加载的插件,交互式程序,我试图对api调用的顺序进行逆向工程...)

所以我最终做的是编写一个调用pycparse的python脚本。我将它包含在它的情况下,以帮助其他人,但它根本不是一般的(假设所有函数都返回int,并且有一个hack来避免typedef中的func defs)。

from pycparser import parse_file 
from pycparser.c_ast import NodeVisitor 


class AncestorVisitor(NodeVisitor): 

    def __init__(self): 
     self.current = None 
     self.ancestors = [] 

    def visit(self, node): 
     if self.current: 
      self.ancestors.append(self.current) 
     self.current = node 
     try: 
      return super(AncestorVisitor, self).visit(node) 
     finally: 
      if self.ancestors: 
       self.ancestors.pop(-1) 


class FunctionVisitor(AncestorVisitor): 

    def visit_FuncDecl(self, node): 
     if len(self.ancestors) < 3: # avoid typedefs 
      print node.type.type.names[0], node.type.declname, '(', 
      first = True 
      for param in node.args.params: 
       if first: first = False 
       else: print ',', 
       print param.type.type.names[0], param.type.declname, 
      print ')' 
      print '{fprintf(stderr, "%s\\n"); return 0;}' % node.type.declname 


print '#include "myheader.h"' 
print '#include <stdio.h>' 
ast = parse_file('myheader.h', use_cpp=True) 
FunctionVisitor().visit(ast)