8

I want to generate empty implementations of procedures defined in a header file. Ideally they should return NULL for pointers, 0 for integers, etc, and, in an ideal world, also print to stderr which function was called.

The motivation for this is the need to implement a wrapper that adapts a subset of a complex, existing API (the header file) to another library. Only a small number of the procedures in the API need to be delegated, but it's not clear which ones. So I hope to use an iterative approach, where I run against this auto-generated wrapper, see what is called, implement that with delegation, and repeat.

I've see Automatically generate C++ file from header? but the answers appear to be C++ specific.

So, for people that need the question spelled out in simple terms, how can I automate the generation of such an implementation given the header file? I would prefer an existing tool - my current best guess at a simple solution is using pycparser.

update Thanks guys. Both good answers. Also posted my current hack.

Community
  • 1
  • 1
andrew cooke
  • 45,717
  • 10
  • 93
  • 143
  • Now you haven't really asked a question as far as I see, but I'm guessing your asking for an existing tool that can do this? Unfortunately I don't know any tool, but it sounds basic enough to do a quick python(or any other high level language) implementation to solve it? – Jite Dec 10 '12 at 13:52
  • i've clarified the question. yes, i can write a program to do this. but it's not trivial - it requires a decent parser, for example. the header is large enough, and complex enough, that an ad-hoc regexp based kludge is going to be a time consuming mess. – andrew cooke Dec 10 '12 at 14:00
  • Hi, does the process need to be easily repeatable? For instance, would you want to be able to update the stub implementation when new versions of the API are released? – OlduwanSteve Dec 10 '12 at 14:02
  • oh good question. no, that's not necessary (it would be better if so, but i can see it making things hugely more complicated, and it's a standard API that is unlikely to change significantly). – andrew cooke Dec 10 '12 at 14:04
  • If you're comfortable with scripting, perhaps you can write your own tool? This looks like a relatively straight-forward task that regular expressions can handle... – RonaldBarzell Dec 10 '12 at 14:04
  • It should be as easy as right click -> source -> generate getters and setters in Eclipse. or not. other than that maybe you could look for some micro C compiler student example and build it up a little bit. – Shark Dec 10 '12 at 14:06

3 Answers3

2

so, i'm going to mark the ea suggestion as the "answer" because i think it's probably the best idea in general. although i think that the cmock suggestion would work very well in tdd approach where the library development was driven by test failures, and i may end up trying that. but for now, i need a quicker + dirtier approach that works in an interactive way (the library in question is a dynamically loaded plugin for another, interactive, program, and i am trying to reverse engineer the sequence of api calls...)

so what i ended up doing was writing a python script that calls pycparse. i'll include it here in case it helps others, but it is not at all general (assumes all functions return int, for example, and has a hack to avoid func defs inside typedefs).

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)
andrew cooke
  • 45,717
  • 10
  • 93
  • 143
1

Caveat: this is an unresearched answer as I haven't had any experience with it myself.

I think you might have some luck with a mocking framework designed for unit testing. An example of such a framework is: cmock

The project page suggests it will generate code from a header. You could then take the code and tweak it.

OlduwanSteve
  • 1,263
  • 14
  • 16
  • that's an interesting idea, thanks. i'm currently in the middle of battling with cpp just to get the header in the format i want, but will think more about this approach. – andrew cooke Dec 10 '12 at 14:24
1

UML modeling tools are capable of generating default implementation in the language of choice. Generally there is also a support for importing source code (including C headers). You can try to import your headers and generate source code from them. I personally have experience with Enterprise Architect and it supports both of these operations.

SomeWittyUsername
  • 18,025
  • 3
  • 42
  • 85
  • ah yes, ea would probably do this (though not the print statements). although maybe only in the paid version, and i haven't had a licence for years. will check it out. thanks. – andrew cooke Dec 10 '12 at 22:19
  • I believe there are free tools as well that can do this stuff, ask google – SomeWittyUsername Dec 10 '12 at 22:23
  • it used to be the case that free uml tools sucked terribly (am a fan of ea, just don't have clients that want uml), but it may have changed. will look. – andrew cooke Dec 10 '12 at 22:58