wrap_openvr.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #! python3
  2. import shlex
  3. import sys
  4. import re
  5. import io
  6. header = open('openvr.h', newline='\n').read()
  7. annoyingMacroPattern = re.compile(r'#define\s+(\w+).*VR_CLANG_ATTR.*')
  8. fullClassPattern = re.compile(r'^([^\S\n]*)class\s+(\w+).*?\{.*?\};', re.MULTILINE | re.DOTALL)
  9. virtualPattern = re.compile(r'([^\S\n]*)virtual\s(.*?)(\w+)(\((.+?,\s*)*.*?\s*\))\s*=\s*0\s*;[^\S\n]*', re.MULTILINE)
  10. optionalParamPattern = re.compile(r'\s*=\s*[^,)]+')
  11. versionPattern = re.compile(r'\s*static\s*const\s*char\s*\*\s*const\s*IVR\w+\s*=\s*\"IVR\w+\";')
  12. annoyingMacros = [match.group(1) for match in annoyingMacroPattern.finditer(header)]
  13. newHeader = header
  14. for match in versionPattern.finditer(newHeader):
  15. newHeader = newHeader.replace(match.group(0), match.group(0).replace('"IVR', '"FnTable:IVR'))
  16. for match in fullClassPattern.finditer(header):
  17. if match.group(0).find('virtual') == -1:
  18. continue
  19. fullClass = match.group(0)
  20. indent = match.group(1)
  21. className = match.group(2)
  22. newClass = fullClass
  23. declarations = []
  24. for function in virtualPattern.finditer(fullClass):
  25. returnType = function.group(2)
  26. functionName = function.group(3)
  27. params = function.group(4)
  28. paramsNoDefault = re.sub(optionalParamPattern, '', params)
  29. for macro in annoyingMacros:
  30. paramsNoDefault = re.sub(macro + r'\(.*?\)', '', paramsNoDefault)
  31. args = []
  32. paramTokens = list(shlex.shlex(io.StringIO(paramsNoDefault)))
  33. for i, token in enumerate(paramTokens):
  34. if token == ',' or (token == ')' and paramTokens[i - 1] not in ['(', 'void']):
  35. args.append(paramTokens[i - 1])
  36. declaration = indent + '\t{}(__stdcall *{}){};'.format(returnType, functionName, paramsNoDefault)
  37. definition = indent + '\t' + returnType + functionName + params + ' { '
  38. if returnType.strip() != 'void':
  39. definition = definition + 'return '
  40. definition = definition + '_table.' + functionName + '(' + ', '.join(args) + '); }'
  41. declarations.append(declaration)
  42. newClass = newClass.replace(function.group(0), definition)
  43. tableName = 'VR_{}_FnTable'.format(className)
  44. table = indent + 'struct ' + tableName + '\n' + indent + '{\n' + '\n'.join(declarations) + '\n' + indent + '};\n\n'
  45. newClass = newClass.replace('public:', '\t{} _table;\n{}public:'.format(tableName, indent))
  46. newHeader = newHeader.replace(fullClass, table + newClass)
  47. open('openvr_mingw.hpp', 'w', newline='\n').write(newHeader)