import os
import re
REdefine = re.compile(r''
r'(?P<desc>)' r'#\s*define\s(?P<name>[^(\n]+?)\s(?P<code>.+)$' , re.MULTILINE)
REstructs = re.compile(r''
r'//\s?[\-]*\s(?P<desc>.*?)\*/\W*?' r'struct\s(?:ASSIMP_API\s)?(?P<name>[a-z][a-z0-9_]\w+\b)' r'[^{]*?\{' r'(?P<code>.*?)' r'\}\s*(PACK_STRUCT)?;' , re.IGNORECASE + re.DOTALL + re.MULTILINE)
REdesc = re.compile(r''
r'^\s*?([*]|/\*\*)(?P<line>.*?)' , re.IGNORECASE + re.DOTALL + re.MULTILINE)
RErmifdef = re.compile(r''
r'#ifdef __cplusplus' r'(?P<code>.*)' r'#endif(\s*//\s*!?\s*__cplusplus)*' , re.IGNORECASE + re.DOTALL)
RErpcom = re.compile(r''
r'\s*(/\*+\s|\*+/|\B\*\s|///?!?)' r'(?P<line>.*?)' , re.IGNORECASE + re.DOTALL)
def GetType(type, prefix='c_'):
t = type
while t.endswith('*'):
t = t[:-1]
if t[:5] == 'const':
t = t[5:]
if t in skiplist:
return None
t = t.strip()
types = {'unsigned int':'uint', 'unsigned char':'ubyte',}
if t in types:
t = types[t]
t = prefix + t
while type.endswith('*'):
t = "POINTER(" + t + ")"
type = type[:-1]
return t
def restructure( match ):
type = match.group("type")
if match.group("struct") == "":
type = GetType(type)
elif match.group("struct") == "C_ENUM ":
type = "c_uint"
else:
type = GetType(type[2:], '')
if type is None:
return ''
if match.group("index"):
type = type + "*" + match.group("index")
result = ""
for name in match.group("name").split(','):
result += "(\"" + name.strip() + "\", "+ type + "),"
return result
RErestruc = re.compile(r''
r'(?P<struct>C_STRUCT\s|C_ENUM\s|)' r'(?P<type>\w+\s?\w+?[*]*)\s' r'(?P<name>\w+|[a-z0-9_, ]+)' r'(:?\[(?P<index>\w+)\])?;' , re.DOTALL)
template = """
class $NAME$(Structure):
\"\"\"
$DESCRIPTION$
\"\"\"
$DEFINES$
_fields_ = [
$FIELDS$
]
"""
templateSR = """
class $NAME$(Structure):
\"\"\"
$DESCRIPTION$
\"\"\"
$DEFINES$
$NAME$._fields_ = [
$FIELDS$
]
"""
skiplist = ("FileIO", "File", "locateFromAssimpHeap",'LogStream','MeshAnim','AnimMesh')
def Structify(fileName):
file = open(fileName, 'r')
text = file.read()
result = []
defs = REdefine.findall(text)
defines = "\n"
for define in defs:
desc = REdesc.sub('', define[0])
desc = RErpcom.sub('#\g<line>', desc)
defines += desc
if len(define[2].strip()):
try:
int(define[2],0)
except:
continue
defines += " "*4 + define[1] + " = " + define[2] + "\n"
rs = REstructs.finditer(text)
fileName = os.path.basename(fileName)
print fileName
for r in rs:
name = r.group('name')[2:]
desc = r.group('desc')
if name in skiplist:
continue
text = r.group('code')
desc = REdesc.sub('', desc)
desc = "See '"+ fileName +"' for details."
text = RErmifdef.sub('', text)
primitive = text.find('C_STRUCT') == -1
text = RErestruc.sub(restructure, text)
text = RErpcom.sub('# \g<line>', text)
text = text.replace("),#", "),\n#")
text = text.replace("#", "\n#")
text = "".join([l for l in text.splitlines(True) if not l.strip().endswith("#")])
selfreferencing = text.find('POINTER('+name+')') != -1
complex = name == "Scene"
description = ""
for line in desc.split('\n'):
description += " "*4 + line.strip() + "\n"
description = description.rstrip()
fields = ""
for line in text.split('\n'):
fields += " "*12 + line.strip() + "\n"
fields = fields.strip()
if selfreferencing:
templ = templateSR
else:
templ = template
text = templ.replace('$NAME$', name)
text = text.replace('$DESCRIPTION$', description)
text = text.replace('$FIELDS$', fields)
if ((name.lower() == fileName.split('.')[0][2:].lower()) and (name != 'Material')) or name == "String":
text = text.replace('$DEFINES$', defines)
else:
text = text.replace('$DEFINES$', '')
result.append((primitive, selfreferencing, complex, text))
return result
text = "#-*- coding: UTF-8 -*-\n\n"
text += "from ctypes import POINTER, c_int, c_uint, c_size_t, c_char, c_float, Structure, c_char_p, c_double, c_ubyte\n\n"
structs1 = ""
structs2 = ""
structs3 = ""
structs4 = ""
path = '../../../include/assimp'
files = os.listdir (path)
for fileName in files:
if fileName.endswith('.h'):
for struct in Structify(os.path.join(path, fileName)):
primitive, sr, complex, struct = struct
if primitive:
structs1 += struct
elif sr:
structs2 += struct
elif complex:
structs4 += struct
else:
structs3 += struct
text += structs1 + structs2 + structs3 + structs4
file = open('structs.py', 'w')
file.write(text)
file.close()
print("Generation done. You can now review the file 'structs.py' and merge it.")