mirror of
https://github.com/ValveSoftware/Proton.git
synced 2024-12-28 15:45:50 +03:00
0f80f2f52c
This alters the behaviour of python2's print statement to be compatible with python3's print function. While not strictly necessary for now, this might help future compatibility. Thanks to Seppo Yli-Olli (@nanonyme) for suggesting this.
535 lines
20 KiB
Python
Executable File
535 lines
20 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
#NOTE: If you make modifications here, consider whether they should
|
|
#be duplicated in ../vrclient/gen_wrapper.py
|
|
|
|
from __future__ import print_function
|
|
|
|
import pprint
|
|
import sys
|
|
import clang.cindex
|
|
import os
|
|
import re
|
|
|
|
sdk_versions = [
|
|
"142",
|
|
"141",
|
|
"140",
|
|
"139",
|
|
"138a",
|
|
"138",
|
|
"137",
|
|
"136",
|
|
"135a",
|
|
"135",
|
|
"134",
|
|
"133b",
|
|
"133a",
|
|
"133",
|
|
"132",
|
|
"131",
|
|
"130",
|
|
"129a",
|
|
"129",
|
|
"128",
|
|
"127",
|
|
"126a",
|
|
"126",
|
|
"125",
|
|
"124",
|
|
"123a",
|
|
"123",
|
|
"122",
|
|
"121",
|
|
"120",
|
|
"119",
|
|
"118",
|
|
"117",
|
|
"116",
|
|
"115",
|
|
"114",
|
|
"113",
|
|
"112",
|
|
"111",
|
|
"110",
|
|
"109",
|
|
"108",
|
|
"107",
|
|
"106",
|
|
"105",
|
|
"104",
|
|
"103",
|
|
"102",
|
|
"101",
|
|
"100",
|
|
]
|
|
|
|
files = [
|
|
("steam_api.h", [
|
|
"ISteamApps",
|
|
"ISteamAppList",
|
|
"ISteamClient",
|
|
"ISteamController",
|
|
"ISteamFriends",
|
|
"ISteamHTMLSurface",
|
|
"ISteamHTTP",
|
|
"ISteamInventory",
|
|
"ISteamMatchmaking",
|
|
"ISteamMatchmakingServers",
|
|
"ISteamMusic",
|
|
"ISteamMusicRemote",
|
|
"ISteamNetworking",
|
|
"ISteamRemoteStorage",
|
|
"ISteamScreenshots",
|
|
"ISteamUGC",
|
|
"ISteamUnifiedMessages",
|
|
"ISteamUser",
|
|
"ISteamUserStats",
|
|
"ISteamUtils",
|
|
"ISteamVideo"
|
|
]),
|
|
("isteamappticket.h", [
|
|
"ISteamAppTicket"
|
|
]),
|
|
("isteamgameserver.h", [
|
|
"ISteamGameServer"
|
|
]),
|
|
("isteamgameserverstats.h", [
|
|
"ISteamGameServerStats"
|
|
]),
|
|
("isteammasterserverupdater.h", [
|
|
"ISteamMasterServerUpdater"
|
|
]),
|
|
("isteamgamecoordinator.h", [
|
|
"ISteamGameCoordinator"
|
|
]),
|
|
("isteamparentalsettings.h", [
|
|
"ISteamParentalSettings"
|
|
]),
|
|
]
|
|
|
|
aliases = {
|
|
#Some interface versions are not present in the public SDK
|
|
#headers, but are actually requested by games. It would be nice
|
|
#to verify that these interface versions are actually binary
|
|
#compatible. Lacking that, we hope the next highest version
|
|
#is compatible.
|
|
"SteamClient012":["SteamClient013"],
|
|
"SteamUtils004":["SteamUtils003"], # TimeShift uses SteamUtils003
|
|
|
|
|
|
#leaving these commented-out. let's see if they turn up in practice,
|
|
#and handle them correctly if so.
|
|
|
|
# "SteamFriends011":["SteamFriends010"],
|
|
# "SteamFriends013":["SteamFriends012"],
|
|
# "SteamGameServer008":["SteamGameServer007", "SteamGameServer006"],
|
|
# "SteamMatchMaking004":["SteamMatchMaking003"],
|
|
# "SteamMatchMaking006":["SteamMatchMaking005"],
|
|
# "STEAMREMOTESTORAGE_INTERFACE_VERSION004":["STEAMREMOTESTORAGE_INTERFACE_VERSION003"],
|
|
# "STEAMREMOTESTORAGE_INTERFACE_VERSION008":["STEAMREMOTESTORAGE_INTERFACE_VERSION007"],
|
|
# "STEAMREMOTESTORAGE_INTERFACE_VERSION010":["STEAMREMOTESTORAGE_INTERFACE_VERSION009"],
|
|
# "STEAMUGC_INTERFACE_VERSION005":["STEAMUGC_INTERFACE_VERSION004"],
|
|
# "STEAMUGC_INTERFACE_VERSION007":["STEAMUGC_INTERFACE_VERSION006"],
|
|
# "SteamUser016":["SteamUser015"],
|
|
# "STEAMUSERSTATS_INTERFACE_VERSION009":["STEAMUSERSTATS_INTERFACE_VERSION008"],
|
|
}
|
|
|
|
# TODO: we could do this automatically by creating temp files and
|
|
# having clang parse those and detect when the MS-style padding results
|
|
# in identical struct widths. But there's only a couple, so let's cheat...
|
|
skip_structs = [
|
|
"RemoteStorageGetPublishedFileDetailsResult_t_9740",
|
|
"SteamUGCQueryCompleted_t_20",
|
|
"SteamUGCRequestUGCDetailsResult_t_9764"
|
|
]
|
|
|
|
print_sizes = []
|
|
|
|
class_versions = {}
|
|
|
|
def handle_destructor(cfile, classname, winclassname, method):
|
|
cfile.write("DEFINE_THISCALL_WRAPPER(%s_destructor, 4)\n" % winclassname)
|
|
cfile.write("void __thiscall %s_destructor(%s *_this)\n{/* never called */}\n\n" % (winclassname, winclassname))
|
|
return "destructor"
|
|
|
|
def handle_method(cfile, classname, winclassname, cppname, method, cpp, cpp_h, existing_methods):
|
|
used_name = method.spelling
|
|
idx = '2'
|
|
while used_name in existing_methods:
|
|
used_name = "%s_%s" % (method.spelling, idx)
|
|
idx = chr(ord(idx) + 1)
|
|
returns_record = method.result_type.get_canonical().kind == clang.cindex.TypeKind.RECORD
|
|
if returns_record:
|
|
parambytes = 8 #_this + return pointer
|
|
else:
|
|
parambytes = 4 #_this
|
|
for param in list(method.get_children()):
|
|
if param.kind == clang.cindex.CursorKind.PARM_DECL:
|
|
parambytes += param.type.get_size()
|
|
cfile.write("DEFINE_THISCALL_WRAPPER(%s_%s, %s)\n" % (winclassname, used_name, parambytes))
|
|
cpp_h.write("extern ")
|
|
if method.result_type.spelling.startswith("ISteam"):
|
|
cfile.write("win%s " % (method.result_type.spelling))
|
|
cpp.write("void *")
|
|
cpp_h.write("void *")
|
|
elif returns_record:
|
|
cfile.write("%s *" % method.result_type.spelling)
|
|
cpp.write("%s " % (method.result_type.spelling))
|
|
cpp_h.write("%s " % (method.result_type.spelling))
|
|
else:
|
|
cfile.write("%s " % (method.result_type.spelling))
|
|
cpp.write("%s " % (method.result_type.spelling))
|
|
cpp_h.write("%s " % (method.result_type.spelling))
|
|
cfile.write('__thiscall %s_%s(%s *_this' % (winclassname, used_name, winclassname))
|
|
cpp.write("%s_%s(void *linux_side" % (cppname, used_name))
|
|
cpp_h.write("%s_%s(void *" % (cppname, used_name))
|
|
if returns_record:
|
|
cfile.write(", %s *_r" % method.result_type.spelling)
|
|
unnamed = 'a'
|
|
for param in list(method.get_children()):
|
|
if param.kind == clang.cindex.CursorKind.PARM_DECL:
|
|
if param.type.kind == clang.cindex.TypeKind.POINTER and \
|
|
param.type.get_pointee().kind == clang.cindex.TypeKind.UNEXPOSED:
|
|
#unspecified function pointer
|
|
typename = "void *"
|
|
else:
|
|
typename = param.type.spelling.split("::")[-1];
|
|
if param.spelling == "":
|
|
cfile.write(", %s _%s" % (typename, unnamed))
|
|
cpp.write(", %s _%s" % (typename, unnamed))
|
|
cpp_h.write(", %s" % typename)
|
|
unnamed = chr(ord(unnamed) + 1)
|
|
else:
|
|
cfile.write(", %s %s" % (typename, param.spelling))
|
|
cpp.write(", %s %s" % (typename, param.spelling))
|
|
cpp_h.write(", %s" % (typename))
|
|
cfile.write(")\n{\n")
|
|
cpp.write(")\n{\n")
|
|
cpp_h.write(");\n")
|
|
|
|
char_param_is_unix_path = "GetAppInstallDir" in used_name or \
|
|
"GetItemInstallInfo" in used_name
|
|
path_param_name = None
|
|
path_size_param_name = None
|
|
|
|
if char_param_is_unix_path:
|
|
cfile.write(" uint32 path_result;\n")
|
|
|
|
cfile.write(" TRACE(\"%p\\n\", _this);\n")
|
|
|
|
if method.result_type.kind == clang.cindex.TypeKind.VOID:
|
|
cfile.write(" ")
|
|
cpp.write(" ")
|
|
elif char_param_is_unix_path:
|
|
cfile.write(" path_result = ")
|
|
cpp.write(" return ")
|
|
elif returns_record:
|
|
cfile.write(" *_r = ")
|
|
cpp.write(" return ")
|
|
else:
|
|
cfile.write(" return ")
|
|
cpp.write(" return ")
|
|
|
|
should_gen_wrapper = method.result_type.spelling.startswith("ISteam") or \
|
|
used_name.startswith("GetISteamGenericInterface")
|
|
if should_gen_wrapper:
|
|
cfile.write("create_win_interface(pchVersion,\n ")
|
|
|
|
cfile.write("%s_%s(_this->linux_side" % (cppname, used_name))
|
|
cpp.write("((%s*)linux_side)->%s(" % (classname, method.spelling))
|
|
unnamed = 'a'
|
|
first = True
|
|
for param in list(method.get_children()):
|
|
if param.kind == clang.cindex.CursorKind.PARM_DECL:
|
|
if not first:
|
|
cpp.write(", ")
|
|
else:
|
|
first = False
|
|
if char_param_is_unix_path:
|
|
if param.type.spelling == "char *":
|
|
path_param_name = param.spelling
|
|
elif not path_param_name is None and \
|
|
(param.type.spelling == "uint32" or
|
|
param.type.spelling == "int"):
|
|
path_size_param_name = param.spelling
|
|
if param.spelling == "":
|
|
cfile.write(", _%s" % unnamed)
|
|
cpp.write("(%s)_%s" % (param.type.spelling, unnamed))
|
|
unnamed = chr(ord(unnamed) + 1)
|
|
elif "ISteamMatchmakingServerListResponse" in param.type.spelling:
|
|
cfile.write(", create_LinuxMatchmakingServerListResponse(%s)" % param.spelling)
|
|
cpp.write("(%s)%s" % (param.type.spelling, param.spelling))
|
|
else:
|
|
cfile.write(", %s" % param.spelling)
|
|
cpp.write("(%s)%s" % (param.type.spelling, param.spelling))
|
|
if should_gen_wrapper:
|
|
cfile.write(")")
|
|
cfile.write(");\n")
|
|
cpp.write(");\n")
|
|
if returns_record:
|
|
cfile.write(" return _r;\n")
|
|
if char_param_is_unix_path and not path_param_name is None and not path_size_param_name is None:
|
|
cfile.write(" return steamclient_unix_path_to_dos_path(path_result, %s, %s);\n" % (path_param_name, path_size_param_name))
|
|
cfile.write("}\n\n")
|
|
cpp.write("}\n\n")
|
|
return used_name
|
|
|
|
def get_iface_version(classname):
|
|
# ISteamClient -> STEAMCLIENT_INTERFACE_VERSION
|
|
defname = "%s_INTERFACE_VERSION" % classname[1:].upper()
|
|
if defname in iface_versions.keys():
|
|
ver = iface_versions[defname]
|
|
else:
|
|
ver = "UNVERSIONED"
|
|
if classname in class_versions.keys() and ver in class_versions[classname]:
|
|
return (ver, True)
|
|
if not classname in class_versions.keys():
|
|
class_versions[classname] = []
|
|
class_versions[classname].append(ver)
|
|
return (ver, False)
|
|
|
|
def handle_class(sdkver, classnode):
|
|
children = list(classnode.get_children())
|
|
if len(children) == 0:
|
|
return
|
|
(iface_version, already_generated) = get_iface_version(classnode.spelling)
|
|
if already_generated:
|
|
return
|
|
winname = "win%s" % classnode.spelling
|
|
cppname = "cpp%s_%s" % (classnode.spelling, iface_version)
|
|
|
|
file_exists = os.path.isfile("%s.c" % winname)
|
|
cfile = open("%s.c" % winname, "a")
|
|
if not file_exists:
|
|
cfile.write("""/* This file is auto-generated, do not edit. */
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "wine/debug.h"
|
|
|
|
#include "cxx.h"
|
|
|
|
#include "steam_defs.h"
|
|
|
|
#include "steamclient_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(steamclient);
|
|
|
|
""")
|
|
|
|
cpp = open("%s.cpp" % cppname, "w")
|
|
cpp.write("#include \"steamclient_private.h\"\n")
|
|
cpp.write("#include \"steam_defs.h\"\n")
|
|
cpp.write("#include \"steamworks_sdk_%s/steam_api.h\"\n" % sdkver)
|
|
if not fname == "steam_api.h":
|
|
cpp.write("#include \"steamworks_sdk_%s/%s\"\n" % (sdkver, fname))
|
|
cpp.write("#include \"%s.h\"\n" % cppname)
|
|
cpp.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n")
|
|
|
|
cpp_h = open("%s.h" % cppname, "w")
|
|
cpp_h.write("#ifdef __cplusplus\nextern \"C\" {\n#endif\n")
|
|
|
|
winclassname = "win%s_%s" % (classnode.spelling, iface_version)
|
|
cfile.write("#include \"%s.h\"\n\n" % cppname)
|
|
cfile.write("typedef struct __%s {\n" % winclassname)
|
|
cfile.write(" vtable_ptr *vtable;\n")
|
|
cfile.write(" void *linux_side;\n")
|
|
cfile.write("} %s;\n\n" % winclassname)
|
|
methods = []
|
|
for child in children:
|
|
if child.kind == clang.cindex.CursorKind.CXX_METHOD:
|
|
methods.append(handle_method(cfile, classnode.spelling, winclassname, cppname, child, cpp, cpp_h, methods))
|
|
elif child.kind == clang.cindex.CursorKind.DESTRUCTOR:
|
|
methods.append(handle_destructor(cfile, classnode.spelling, winclassname, child))
|
|
|
|
cfile.write("extern vtable_ptr %s_vtable;\n\n" % winclassname)
|
|
cfile.write("#ifndef __GNUC__\n")
|
|
cfile.write("void __asm_dummy_vtables(void) {\n")
|
|
cfile.write("#endif\n")
|
|
cfile.write(" __ASM_VTABLE(%s,\n" % winclassname)
|
|
for method in methods:
|
|
cfile.write(" VTABLE_ADD_FUNC(%s_%s)\n" % (winclassname, method))
|
|
cfile.write(" );\n")
|
|
cfile.write("#ifndef __GNUC__\n")
|
|
cfile.write("}\n")
|
|
cfile.write("#endif\n\n")
|
|
cfile.write("%s *create_%s(void *linux_side)\n{\n" % (winclassname, winclassname))
|
|
cfile.write(" %s *r = HeapAlloc(GetProcessHeap(), 0, sizeof(%s));\n" % (winclassname, winclassname))
|
|
cfile.write(" TRACE(\"-> %p\\n\", r);\n")
|
|
cfile.write(" r->vtable = &%s_vtable;\n" % winclassname)
|
|
cfile.write(" r->linux_side = linux_side;\n")
|
|
cfile.write(" return r;\n}\n\n")
|
|
|
|
cpp.write("#ifdef __cplusplus\n}\n#endif\n")
|
|
cpp_h.write("#ifdef __cplusplus\n}\n#endif\n")
|
|
|
|
constructors = open("win_constructors.h", "a")
|
|
constructors.write("extern void *create_%s(void *);\n" % winclassname)
|
|
|
|
constructors = open("win_constructors_table.dat", "a")
|
|
constructors.write(" {\"%s\", &create_%s},\n" % (iface_version, winclassname))
|
|
if iface_version in aliases.keys():
|
|
for alias in aliases[iface_version]:
|
|
constructors.write(" {\"%s\", &create_%s}, /* alias */\n" % (alias, winclassname))
|
|
|
|
|
|
generated_cb_handlers = []
|
|
generated_cb_ids = []
|
|
cpp_files_need_close_brace = []
|
|
cb_table = {}
|
|
|
|
#because of struct packing differences between win32 and linux, we
|
|
#need to convert these structs from their linux layout to the win32
|
|
#layout.
|
|
#TODO: could we optimize this by detecting if the structs are the
|
|
#same layout at generation-time?
|
|
def handle_callback_struct(sdkver, callback, cb_num):
|
|
handler_name = "%s_%s" % (callback.displayname, callback.type.get_size())
|
|
|
|
if handler_name in generated_cb_handlers:
|
|
# we already have a handler for the callback struct of this size
|
|
return
|
|
|
|
if handler_name in skip_structs:
|
|
# due to padding, some structs have the same width across versions of
|
|
# the SDK. since we key our lin->win conversion on the win struct size,
|
|
# we can skip the smaller structs and just write into the padding on
|
|
# older versions
|
|
# TODO: we could automate this. see comment near skip_structs declaration
|
|
return
|
|
|
|
cb_id = cb_num | (callback.type.get_size() << 16)
|
|
if cb_id in generated_cb_ids:
|
|
# either this cb changed name, or steam used the same ID for different structs
|
|
return
|
|
|
|
generated_cb_ids.append(cb_id)
|
|
|
|
filename_base = "cb_converters_%s" % sdkver
|
|
cppname = "%s.cpp" % filename_base
|
|
file_exists = os.path.isfile(cppname)
|
|
cppfile = open(cppname, "a")
|
|
if not file_exists:
|
|
cppfile.write("#include \"steamclient_private.h\"\n")
|
|
cppfile.write("#include \"steam_defs.h\"\n")
|
|
cppfile.write("#include \"steamworks_sdk_%s/steam_api.h\"\n" % sdkver)
|
|
cppfile.write("#include \"steamworks_sdk_%s/isteamgameserver.h\"\n" % (sdkver))
|
|
if os.path.isfile("steamworks_sdk_%s/isteamgameserverstats.h" % sdkver):
|
|
cppfile.write("#include \"steamworks_sdk_%s/isteamgameserverstats.h\"\n" % (sdkver))
|
|
if os.path.isfile("steamworks_sdk_%s/isteamgamecoordinator.h" % sdkver):
|
|
cppfile.write("#include \"steamworks_sdk_%s/isteamgamecoordinator.h\"\n" % sdkver)
|
|
cppfile.write("extern \"C\" {\n")
|
|
cpp_files_need_close_brace.append(cppname)
|
|
|
|
datfile = open("cb_converters.dat", "a")
|
|
datfile.write("case 0x%08x: win_msg->m_cubParam = sizeof(struct win%s); win_msg->m_pubParam = HeapAlloc(GetProcessHeap(), 0, win_msg->m_cubParam); cb_%s(lin_msg.m_pubParam, win_msg->m_pubParam); break;\n" % (cb_id, handler_name, handler_name))
|
|
|
|
hfile = open("cb_converters.h", "a")
|
|
hfile.write("struct win%s {\n" % handler_name)
|
|
for m in callback.get_children():
|
|
if m.kind == clang.cindex.CursorKind.FIELD_DECL:
|
|
if m.type.kind == clang.cindex.TypeKind.CONSTANTARRAY:
|
|
hfile.write(" %s %s[%u];\n" % (m.type.element_type.spelling, m.displayname, m.type.element_count))
|
|
else:
|
|
hfile.write(" %s %s;\n" % (m.type.spelling, m.displayname))
|
|
hfile.write("} __attribute__ ((ms_struct));\n")
|
|
hfile.write("extern void cb_%s(void *l, void *w);\n" % handler_name)
|
|
|
|
cppfile.write("struct win%s {\n" % handler_name)
|
|
for m in callback.get_children():
|
|
if m.kind == clang.cindex.CursorKind.FIELD_DECL:
|
|
if m.type.kind == clang.cindex.TypeKind.CONSTANTARRAY:
|
|
cppfile.write(" %s %s[%u];\n" % (m.type.element_type.spelling, m.displayname, m.type.element_count))
|
|
else:
|
|
cppfile.write(" %s %s;\n" % (m.type.spelling, m.displayname))
|
|
cppfile.write("} __attribute__ ((ms_struct));\n")
|
|
|
|
cppfile.write("void cb_%s(void *l, void *w)\n{\n" % handler_name)
|
|
cppfile.write(" %s *lin = (%s *)l;\n" % (callback.displayname, callback.displayname))
|
|
cppfile.write(" struct win%s *win = (struct win%s *)w;\n" % (handler_name, handler_name))
|
|
for m in callback.get_children():
|
|
if m.kind == clang.cindex.CursorKind.FIELD_DECL:
|
|
if m.type.kind == clang.cindex.TypeKind.CONSTANTARRAY:
|
|
#TODO: if this is a struct, or packed differently, we'll have to
|
|
# copy each element in a for-loop
|
|
cppfile.write(" memcpy(win->%s, lin->%s, sizeof(win->%s));\n" % (m.displayname, m.displayname, m.displayname))
|
|
else:
|
|
cppfile.write(" win->%s = lin->%s;\n" % (m.displayname, m.displayname))
|
|
cppfile.write("}\n\n")
|
|
|
|
generated_cb_handlers.append(handler_name)
|
|
|
|
if not cb_num in cb_table.keys():
|
|
# latest SDK linux size, list of windows struct names
|
|
cb_table[cb_num] = (callback.type.get_size(), [])
|
|
cb_table[cb_num][1].append(handler_name)
|
|
|
|
|
|
def handle_callback_maybe(sdkver, callback):
|
|
members = callback.get_children()
|
|
for c in members:
|
|
if c.kind == clang.cindex.CursorKind.ENUM_DECL:
|
|
enums = c.get_children()
|
|
for e in enums:
|
|
if e.displayname == "k_iCallback":
|
|
handle_callback_struct(sdkver, callback, e.enum_value)
|
|
|
|
|
|
|
|
|
|
#clang.cindex.Config.set_library_file("/usr/lib/llvm-3.8/lib/libclang-3.8.so.1");
|
|
|
|
prog = re.compile("^#define\s*(\w*)\s*\"(.*)\"")
|
|
for sdkver in sdk_versions:
|
|
iface_versions = {}
|
|
for f in os.listdir("steamworks_sdk_%s" % sdkver):
|
|
x = open("steamworks_sdk_%s/%s" % (sdkver, f), "r")
|
|
for l in x:
|
|
if "INTERFACE_VERSION" in l:
|
|
result = prog.match(l)
|
|
if result:
|
|
iface, version = result.group(1, 2)
|
|
iface_versions[iface] = version
|
|
|
|
for fname, classes in files:
|
|
# Parse as 32-bit C++
|
|
input_name = "steamworks_sdk_%s/%s" % (sdkver, fname)
|
|
sys.stdout.write("about to parse %s\n" % input_name)
|
|
if not os.path.isfile(input_name):
|
|
continue
|
|
index = clang.cindex.Index.create()
|
|
tu = index.parse(input_name, args=['-x', 'c++', '-m32', '-Isteamworks_sdk_%s/' % sdkver, '-I/usr/lib/clang/5.0.1/include/'])
|
|
|
|
diagnostics = list(tu.diagnostics)
|
|
if len(diagnostics) > 0:
|
|
print('There were parse errors')
|
|
pprint.pprint(diagnostics)
|
|
else:
|
|
children = list(tu.cursor.get_children())
|
|
for child in children:
|
|
if child.kind == clang.cindex.CursorKind.CLASS_DECL and child.displayname in classes:
|
|
handle_class(sdkver, child)
|
|
if child.kind == clang.cindex.CursorKind.STRUCT_DECL or \
|
|
child.kind == clang.cindex.CursorKind.CLASS_DECL:
|
|
handle_callback_maybe(sdkver, child)
|
|
if child.displayname in print_sizes:
|
|
sys.stdout.write("size of %s is %u\n" % (child.displayname, child.type.get_size()))
|
|
|
|
for f in cpp_files_need_close_brace:
|
|
m = open(f, "a")
|
|
m.write("\n}\n")
|
|
|
|
getapifile = open("cb_getapi_table.dat", "w")
|
|
cbsizefile = open("cb_getapi_sizes.dat", "w")
|
|
for cb in cb_table.keys():
|
|
cbsizefile.write("case %u: /* %s */\n" % (cb, cb_table[cb][1][0]))
|
|
cbsizefile.write(" return %u;\n" % cb_table[cb][0])
|
|
getapifile.write("case %u:\n" % cb)
|
|
getapifile.write(" switch(callback_len){\n")
|
|
getapifile.write(" default:\n") # the first one should be the latest, should best support future SDK versions
|
|
for struct in cb_table[cb][1]:
|
|
getapifile.write(" case sizeof(struct win%s): cb_%s(lin_callback, callback); break;\n" % (struct, struct))
|
|
getapifile.write(" }\n break;\n")
|