Skip to content

Commit

Permalink
MakeGW improvements (#2180)
Browse files Browse the repository at this point in the history
  • Loading branch information
CristiFati authored Feb 20, 2024
1 parent 3987d6d commit 07f984d
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 17 deletions.
88 changes: 81 additions & 7 deletions com/win32com/makegw/makegw.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
This module will generate a C++/Python binding for a specific COM
interface.
At this stage, no command line interface exists. You must start Python,
import this module, change to the directory where the generated code should
be written, and run the public function.
Can be run from command line (passing required arguments) or the old way
(start Python, import this module, change to the directory where the generated code
should be written, and run the public function).
This module is capable of generating both 'Interfaces' (ie, Python
client side support for the interface) and 'Gateways' (ie, Python
Expand Down Expand Up @@ -46,13 +46,19 @@
"""

import argparse
import os
import re

from . import makegwparse


def make_framework_support(
header_file_name, interface_name, bMakeInterface=1, bMakeGateway=1
header_file_name,
interface_name,
bMakeInterface=1,
bMakeGateway=1,
output_directory=None,
):
"""Generate C++ code for a Python Interface and Gateway
Expand Down Expand Up @@ -86,7 +92,12 @@ def make_framework_support(
ifc_cpp_writer = _write_ifc_cpp
gw_cpp_writer = _write_gw_cpp

fout = open("Py%s.cpp" % interface.name, "w")
fout = open(
os.path.join(
directory if directory else os.getcwd(), f"Py{interface.name}.cpp"
),
"w",
)
try:
fout.write(
f"""\
Expand All @@ -110,7 +121,10 @@ def make_framework_support(
gw_cpp_writer(fout, interface)
finally:
fout.close()
fout = open("Py%s.h" % interface.name, "w")
fout = open(
os.path.join(directory if directory else os.getcwd(), f"Py{interface.name}.h"),
"w",
)
try:
fout.write(
f"""\
Expand Down Expand Up @@ -319,7 +333,7 @@ def _write_ifc_cpp(f, interface):
)
)
else:
f.write("\tPy_INCREF(Py_None);\n\treturn Py_None;\n")
f.write("\tPy_RETURN_NONE;\n")
f.write("\n}\n\n")

f.write("// @object Py%s|Description of the interface\n" % (name))
Expand Down Expand Up @@ -564,3 +578,63 @@ def test():


# make_framework_support("d:\\msdev\\include\\objidl.h", "IEnumSTATSTG")
# python -m com.win32com.makegw.makegw -f "C:\Windows Kits\10\Include\10.0.19041.0\um\ShObjIdl_core.h" -n IFolderView1 -o com\win32comext\shell\src


def parse_arguments():
parser = argparse.ArgumentParser(description="COM interface wrapper generator")
parser.add_argument(
"--header_file", "-f", required=True, help="header file (system) to parse"
)
parser.add_argument(
"--interface_name", "-n", required=True, help="interface name to search for"
)
parser.add_argument(
"--no_create_interface",
"-i",
action="store_false",
dest="create_interface",
help="do not generate interface code",
)
parser.add_argument(
"--no_create_gateway",
"-g",
action="store_false",
dest="create_gateway",
help="do not generate gateway code",
)
parser.add_argument(
"--output_directory", "-o", help="directory where to generate files"
)

args, unk = parser.parse_known_args()
if unk:
print(f"Warning: Ignoring unknown arguments: {unk}")

if not args.header_file or not os.path.isfile(args.header_file):
parser.exit(status=-1, message="Invalid header file\n")
if not args.interface_name:
parser.exit(status=-1, message="Invalid interface name\n")

return (
args.header_file,
args.interface_name,
args.create_interface,
args.create_gateway,
args.output_directory or None,
)


if __name__ == "__main__":
header_file, interface_name, create_interface, create_gateway, directory = (
parse_arguments()
)
if directory:
os.makedirs(directory, exist_ok=True)
make_framework_support(
header_file_name=header_file,
interface_name=interface_name,
bMakeInterface=create_interface,
bMakeGateway=create_gateway,
output_directory=directory,
)
33 changes: 23 additions & 10 deletions com/win32com/makegw/makegwparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,14 @@ def _GetPythonTypeDesc(self):
"LPITEMIDLIST": (ArgFormatterIDLIST, 0, 1),
"LPCITEMIDLIST": (ArgFormatterIDLIST, 0, 1),
"const ITEMIDLIST": (ArgFormatterIDLIST, 0, 1),
"PITEMID_CHILD": (ArgFormatterIDLIST, 1),
"const PITEMID_CHILD": (ArgFormatterIDLIST, 0),
"PCITEMID_CHILD": (ArgFormatterIDLIST, 0),
"PUITEMID_CHILD": (ArgFormatterIDLIST, 1),
"PCUITEMID_CHILD": (ArgFormatterIDLIST, 0),
"const PUITEMID_CHILD": (ArgFormatterIDLIST, 0),
"PCUITEMID_CHILD_ARRAY": (ArgFormatterIDLIST, 2),
"const PCUITEMID_CHILD_ARRAY": (ArgFormatterIDLIST, 2),
}

# Auto-add all the simple types
Expand Down Expand Up @@ -796,11 +804,20 @@ class Argument:
# -------------- -------- ------------ ------
regex = re.compile(r"/\* \[([^\]]*.*?)] \*/[ \t](.*[* ]+)(\w+)(\[ *])?[\),]")

@classmethod
def drop_rpc_metadata(cls, type_):
return " ".join(e for e in type_.split(" ") if not e.startswith("__RPC_"))

def __init__(self, good_interface_names):
self.good_interface_names = good_interface_names
self.inout = self.name = self.type = None
self.inout = None
self.name = None
self.type = None
self.raw_type = None
self.unc_type = None
self.const = 0
self.arrayDecl = 0
self.indirectionLevel = 0

def BuildFromFile(self, file):
"""Parse and build my data from a file
Expand All @@ -817,21 +834,17 @@ def BuildFromFile(self, file):
self.inout = mo.group(1).split("][")
typ = mo.group(2).strip()
self.raw_type = typ
self.indirectionLevel = 0
if mo.group(4): # Has "[ ]" decl
self.arrayDecl = 1
try:
pos = typ.rindex("__RPC_FAR")
self.indirectionLevel = self.indirectionLevel + 1
typ = typ[:pos].strip()
except ValueError:
pass
typ_no_rpc = self.drop_rpc_metadata(typ)
if typ != typ_no_rpc:
self.indirectionLevel += 1

typ = typ.replace("__RPC_FAR", "")
typ = self.drop_rpc_metadata(typ)
while 1:
try:
pos = typ.rindex("*")
self.indirectionLevel = self.indirectionLevel + 1
self.indirectionLevel += 1
typ = typ[:pos].strip()
except ValueError:
break
Expand Down

0 comments on commit 07f984d

Please sign in to comment.