How to import constants from .h file into python module
What is a recommended way to import a bunch of constants defined in a c-style (not c++, just plain old c) .h file into python module so that it can be used in python's part of a project. In the project we use a mix of languages and in perl I can do this importing by using h2xs utility to generate .pm module.
Constants definition looks like
#define FOO 1
enum {
BAR,
BAZ
开发者_开发技巧};
etc.
C-style comments are also presented an have to be properly handled.
I recently used the pyparsing library to scan for enum constants. Here it is, along with a sample string and the resulting output. Notice it also handles comments and commented out sections. With a little modification it could stuff the constants in a dictionary.
from pyparsing import *
sample = '''
stuff before
enum hello {
Zero,
One,
Two,
Three,
Five=5,
Six,
Ten=10
}
in the middle
enum blah
{
alpha, // blah
beta, /* blah blah
gamma = 10 , */
zeta = 50
}
at the end
'''
# syntax we don't want to see in the final parse tree
_lcurl = Suppress('{')
_rcurl = Suppress('}')
_equal = Suppress('=')
_comma = Suppress(',')
_enum = Suppress('enum')
identifier = Word(alphas,alphanums+'_')
integer = Word(nums)
enumValue = Group(identifier('name') + Optional(_equal + integer('value')))
enumList = Group(enumValue + ZeroOrMore(_comma + enumValue))
enum = _enum + identifier('enum') + _lcurl + enumList('list') + _rcurl
enum.ignore(cppStyleComment)
for item,start,stop in enum.scanString(sample):
id = 0
for entry in item.list:
if entry.value != '':
id = int(entry.value)
print '%s_%s = %d' % (item.enum.upper(),entry.name.upper(),id)
id += 1
OUTPUT:
HELLO_ZERO = 0
HELLO_ONE = 1
HELLO_TWO = 2
HELLO_THREE = 3
HELLO_FIVE = 5
HELLO_SIX = 6
HELLO_TEN = 10
BLAH_ALPHA = 0
BLAH_BETA = 1
BLAH_ZETA = 50
I once had to do something similar, and in the end I did something strange but highly reliable. Dealing with all the possibilities for how values might be defined is tricky... for instance, you have to handle
#include "someotherfile.h"
enum NewEnum {
A = -5,
B = SOME_OTHER_ENUM,
C,
D = 3
};
(which is really nasty and no one should ever do...)
In the end, part of my build process was a perl script that parsed the header file for all enums and defines, and then produced a .c file that included the header and was nothing more then a bunch of print statements, printing the actual value for each define. This file was compiled and executed, and the output of that was used to produce the next source file ( Java, in my case ).
This ensured that I got the right values, as I was using the C preprocessor and compiler to produce the answers.
I'd suggest the other way round, if possible: define all your constants in a Python dict or module and auto-generate the .h in Python. It will be much, much easier.
Create a script/program that is called from make and creates the necessary python file. If you only need #define and enum it shouldn't be too hard to write. Then remember NOT to check this python file into source control as you want the build process to force the regeneration of the file every time.
精彩评论