mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
ctypes_generation now handle anonymous sub-struct/union
This commit is contained in:
@@ -231,7 +231,8 @@ class BasicTypeNodes(object):
|
||||
@property
|
||||
def exports(self):
|
||||
# Let allow ourself to redefine the bugged BYTE define & MAX_PATH which is NOT A TYPE !
|
||||
return set(dummy_wintypes.names) - set(["BYTE", "MAX_PATH"])
|
||||
# Also ourself to redifine FILETIME (to trigger the extended struct generation)
|
||||
return set(dummy_wintypes.names) - set(["BYTE", "MAX_PATH", "_FILETIME", "FILETIME"])
|
||||
|
||||
class FakeExporter(object):
|
||||
def __init__(self, exports):
|
||||
|
||||
@@ -24,8 +24,21 @@ class WinStructParser(Parser):
|
||||
|
||||
|
||||
def parse_def(self):
|
||||
if self.peek() == KeywordToken("struct"):
|
||||
discard = self.next_token()
|
||||
if type(self.peek()) != NameToken and self.peek() in (KeywordToken("union"), KeywordToken("struct")):
|
||||
# Anonymous union-structure :)
|
||||
# kword = self.assert_token_type(KeywordToken)
|
||||
# Not a name. Anon union/struct ?
|
||||
subdef_type = self.next_token() # union / struct
|
||||
if type(self.peek()) == OpenBracketToken:
|
||||
print("<{0}> ANON START WITH <{1}>".format(self._yolo, self.peek()))
|
||||
sub = self.parse_winstruct(anonymous=True, anon_type=subdef_type)
|
||||
print("Anon is <{0}>".format(sub))
|
||||
return (sub, NameToken(None), 1)
|
||||
else:
|
||||
# struct _MYNAME_ -> no anon juste the name of the struct.
|
||||
# Nothing special: juste drop the struct
|
||||
assert subdef_type.value == "struct"
|
||||
# Name will be enforced by nest line.
|
||||
|
||||
def_type_tok = self.assert_token_type(NameToken)
|
||||
def_type = WinStructType(def_type_tok.value)
|
||||
@@ -98,14 +111,17 @@ class WinStructParser(Parser):
|
||||
return res_enum
|
||||
|
||||
|
||||
def parse_winstruct(self):
|
||||
def parse_winstruct(self, anonymous=False, anon_type=None):
|
||||
is_typedef = False
|
||||
peeked = self.peek()
|
||||
if peeked == KeywordToken("typedef"):
|
||||
self.assert_keyword("typedef")
|
||||
is_typedef = True
|
||||
|
||||
def_type = self.assert_token_type(KeywordToken)
|
||||
if not anonymous:
|
||||
def_type = self.assert_token_type(KeywordToken)
|
||||
else:
|
||||
def_type = anon_type # Hack car le lexeing a ete fait avant, l'info est donc passee en param.
|
||||
if def_type.value == "enum":
|
||||
return self.parse_enum(is_typedef)
|
||||
if def_type.value == "struct":
|
||||
@@ -118,14 +134,14 @@ class WinStructParser(Parser):
|
||||
# Not an anonymous structure def
|
||||
struct_name = self.assert_token_type(NameToken).value
|
||||
else:
|
||||
# Anonymous structure def: check if we are ina typedef
|
||||
if not is_typedef:
|
||||
# Anonymous structure def: check if we are ina typedef
|
||||
if not is_typedef and not anonymous:
|
||||
raise ValueError("Anonymous structure/union not in a typedef")
|
||||
struct_name = None #
|
||||
struct_name = "anon"
|
||||
self.assert_token_type(OpenBracketToken)
|
||||
self._yolo = struct_name
|
||||
|
||||
result = WinDefType(struct_name, self.pack)
|
||||
|
||||
while type(self.peek()) != CloseBracketToken:
|
||||
tok_type, tok_name, nb_rep = self.parse_def()
|
||||
result.add_field((tok_type, tok_name.value, nb_rep))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import collections
|
||||
import itertools
|
||||
|
||||
#WinStructType = collections.namedtuple('WinStructType', ['name'])
|
||||
|
||||
@@ -58,7 +59,7 @@ class WinStruct(object):
|
||||
if self.name is None:
|
||||
raise ValueError("Anonymous struct first typedef ({0}) should not be a PTR type".format(name))
|
||||
if name in self.typedef:
|
||||
raise ValueError("nop")
|
||||
raise ValueError("Multiple typedef for <{0}>".format(name))
|
||||
self.typedef[name] = Ptr(self)
|
||||
|
||||
def is_self_referencing(self):
|
||||
@@ -69,6 +70,27 @@ class WinStruct(object):
|
||||
return True
|
||||
return False
|
||||
|
||||
def contains_anon_struct(self):
|
||||
return any(name is None for type,name,nb in self.fields)
|
||||
|
||||
def prepare_anon_struct(self):
|
||||
new_fields = []
|
||||
code = []
|
||||
i = 0
|
||||
for type, name, nb in self.fields:
|
||||
if name is not None:
|
||||
new_fields.append((type, name, nb))
|
||||
continue
|
||||
i += 1
|
||||
# Should begin by "_ANON_" to trigger <generate_anonymous_union>
|
||||
type.name = "_ANON_{0}_SUB_{1}_{2}".format(self.name, type.ctypes_type, i).upper()
|
||||
code.append(type.generate_ctypes()) # Generate class for the code
|
||||
# Replace the type name + field name in fields list
|
||||
|
||||
new_fields.append((WinStructType(type.name), "anon_{0:02}".format(i), nb))
|
||||
self.fields = new_fields
|
||||
return "\n".join(code)
|
||||
|
||||
def generate_selfref_ctypes_class(self):
|
||||
res = ["# Self referencing struct tricks"]
|
||||
res += ["""class {0}(Structure): pass""".format(self.name)]
|
||||
@@ -129,13 +151,21 @@ class WinStruct(object):
|
||||
return "\n".join(typedef_ctypes)
|
||||
|
||||
def generate_ctypes(self):
|
||||
anon_code = ""
|
||||
if self.contains_anon_struct():
|
||||
anon_code = self.prepare_anon_struct()
|
||||
|
||||
if self.is_self_referencing():
|
||||
print("{0} is self referencing".format(self.name))
|
||||
return self.generate_selfref_ctypes_class() + "\n"
|
||||
|
||||
|
||||
import pdb;pdb.set_trace()
|
||||
print("LOL")
|
||||
|
||||
ctypes_class = self.generate_ctypes_class()
|
||||
ctypes_typedef = self.generate_typedef_ctypes()
|
||||
return "\n".join([ctypes_class, ctypes_typedef]) + "\n"
|
||||
return anon_code + "\n".join([ctypes_class, ctypes_typedef]) + "\n"
|
||||
|
||||
class WinUnion(WinStruct):
|
||||
ctypes_type = "Union"
|
||||
|
||||
Reference in New Issue
Block a user