Todo: 集成多平台 解决因SaiNiu线程抢占资源问题 本地提交测试环境打包 和 正式打包脚本与正式环境打包bat 提交Python32环境包 改进多日志文件生成情况修改打包日志细节
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# indicates a python package.
|
||||
618
Utils/PythonNew32/Lib/site-packages/win32com/makegw/makegw.py
Normal file
618
Utils/PythonNew32/Lib/site-packages/win32com/makegw/makegw.py
Normal file
@@ -0,0 +1,618 @@
|
||||
"""Utility functions for writing out gateway C++ files
|
||||
|
||||
This module will generate a C++/Python binding for a specific COM
|
||||
interface.
|
||||
|
||||
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
|
||||
server side support for the interface). Many COM interfaces are useful
|
||||
both as Client and Server. Other interfaces, however, really only make
|
||||
sense to implement one side or the other. For example, it would be pointless
|
||||
for Python to implement Server side for 'IRunningObjectTable', unless we were
|
||||
implementing core COM for an operating system in Python (hey - now there's an idea!)
|
||||
|
||||
Most COM interface code is totally boiler-plate - it consists of
|
||||
converting arguments, dispatching the call to Python, and processing
|
||||
any result values.
|
||||
|
||||
This module automates the generation of such code. It has the ability to
|
||||
parse a .h file generated by the MIDL tool (ie, almost all COM .h files)
|
||||
and build almost totally complete C++ code.
|
||||
|
||||
The module understands some of the well known data types, and how to
|
||||
convert them. There are only a couple of places where hand-editing is
|
||||
necessary, as detailed below:
|
||||
|
||||
unsupported types -- If a type is not known, the generator will
|
||||
pretty much ignore it, but write a comment to the generated code. You
|
||||
may want to add custom support for this type. In some cases, C++ compile errors
|
||||
will result. These are intentional - generating code to remove these errors would
|
||||
imply a false sense of security that the generator has done the right thing.
|
||||
|
||||
other return policies -- By default, Python never sees the return SCODE from
|
||||
a COM function. The interface usually returns None if OK, else a COM exception
|
||||
if "FAILED(scode)" is TRUE. You may need to change this if:
|
||||
* EXCEPINFO is passed to the COM function. This is not detected and handled
|
||||
* For some reason Python should always see the result SCODE, even if it
|
||||
did fail or succeed. For example, some functions return a BOOLEAN result
|
||||
in the SCODE, meaning Python should always see it.
|
||||
* FAILED(scode) for the interface still has valid data to return (by default,
|
||||
the code generated does not process the return values, and raise an exception
|
||||
to Python/COM
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
|
||||
from . import makegwparse
|
||||
|
||||
|
||||
def make_framework_support(
|
||||
header_file_name,
|
||||
interface_name,
|
||||
bMakeInterface=1,
|
||||
bMakeGateway=1,
|
||||
output_directory=None,
|
||||
):
|
||||
"""Generate C++ code for a Python Interface and Gateway
|
||||
|
||||
header_file_name -- The full path to the .h file which defines the interface.
|
||||
interface_name -- The name of the interface to search for, and to generate.
|
||||
bMakeInterface = 1 -- Should interface (ie, client) support be generated.
|
||||
bMakeGatewayInterface = 1 -- Should gateway (ie, server) support be generated.
|
||||
|
||||
This method will write a .cpp and .h file into the current directory,
|
||||
(using the name of the interface to build the file name.
|
||||
|
||||
"""
|
||||
fin = open(header_file_name)
|
||||
try:
|
||||
interface = makegwparse.parse_interface_info(interface_name, fin)
|
||||
finally:
|
||||
fin.close()
|
||||
|
||||
if bMakeInterface and bMakeGateway:
|
||||
desc = "Interface and Gateway"
|
||||
elif bMakeInterface and not bMakeGateway:
|
||||
desc = "Interface"
|
||||
else:
|
||||
desc = "Gateway"
|
||||
if interface.name[:5] == "IEnum": # IEnum - use my really simple template-based one
|
||||
import win32com.makegw.makegwenum
|
||||
|
||||
ifc_cpp_writer = win32com.makegw.makegwenum._write_enumifc_cpp
|
||||
gw_cpp_writer = win32com.makegw.makegwenum._write_enumgw_cpp
|
||||
else: # Use my harder working ones.
|
||||
ifc_cpp_writer = _write_ifc_cpp
|
||||
gw_cpp_writer = _write_gw_cpp
|
||||
|
||||
fout = open(
|
||||
os.path.join(
|
||||
directory if directory else os.getcwd(), f"Py{interface.name}.cpp"
|
||||
),
|
||||
"w",
|
||||
)
|
||||
try:
|
||||
fout.write(
|
||||
f"""\
|
||||
// This file implements the {interface.name} {desc} for Python.
|
||||
// Generated by makegw.py
|
||||
|
||||
#include "shell_pch.h"
|
||||
"""
|
||||
)
|
||||
# if bMakeGateway:
|
||||
# fout.write('#include "PythonCOMServer.h"\n')
|
||||
# if interface.base not in ["IUnknown", "IDispatch"]:
|
||||
# fout.write('#include "Py%s.h"\n' % interface.base)
|
||||
fout.write(
|
||||
'#include "Py%s.h"\n\n// @doc - This file contains autoduck documentation\n'
|
||||
% interface.name
|
||||
)
|
||||
if bMakeInterface:
|
||||
ifc_cpp_writer(fout, interface)
|
||||
if bMakeGateway:
|
||||
gw_cpp_writer(fout, interface)
|
||||
finally:
|
||||
fout.close()
|
||||
fout = open(
|
||||
os.path.join(directory if directory else os.getcwd(), f"Py{interface.name}.h"),
|
||||
"w",
|
||||
)
|
||||
try:
|
||||
fout.write(
|
||||
f"""\
|
||||
// This file declares the {interface.name} {desc} for Python.
|
||||
// Generated by makegw.py
|
||||
"""
|
||||
)
|
||||
|
||||
if bMakeInterface:
|
||||
_write_ifc_h(fout, interface)
|
||||
if bMakeGateway:
|
||||
_write_gw_h(fout, interface)
|
||||
finally:
|
||||
fout.close()
|
||||
|
||||
|
||||
###########################################################################
|
||||
#
|
||||
# INTERNAL FUNCTIONS
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
def _write_ifc_h(f, interface):
|
||||
f.write(
|
||||
f"""\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Interface Declaration
|
||||
|
||||
class Py{interface.name} : public Py{interface.base}
|
||||
{{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(Py{interface.name});
|
||||
static {interface.name} *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
"""
|
||||
)
|
||||
for method in interface.methods:
|
||||
f.write(
|
||||
"\tstatic PyObject *%s(PyObject *self, PyObject *args);\n" % method.name
|
||||
)
|
||||
f.write(
|
||||
f"""\
|
||||
|
||||
protected:
|
||||
Py{interface.name}(IUnknown *pdisp);
|
||||
~Py{interface.name}();
|
||||
}};
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def _write_ifc_cpp(f, interface):
|
||||
name = interface.name
|
||||
f.write(
|
||||
"""\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Interface Implementation
|
||||
|
||||
Py{name}::Py{name}(IUnknown *pdisp):
|
||||
Py{base}(pdisp)
|
||||
{{
|
||||
ob_type = &type;
|
||||
}}
|
||||
|
||||
Py{name}::~Py{name}()
|
||||
{{
|
||||
}}
|
||||
|
||||
/* static */ {name} *Py{name}::GetI(PyObject *self)
|
||||
{{
|
||||
return ({name} *)Py{base}::GetI(self);
|
||||
}}
|
||||
|
||||
""".format(**interface.__dict__)
|
||||
)
|
||||
|
||||
ptr = re.sub(r"[a-z]", "", interface.name)
|
||||
strdict = {"interfacename": interface.name, "ptr": ptr}
|
||||
for method in interface.methods:
|
||||
strdict["method"] = method.name
|
||||
f.write(
|
||||
"""\
|
||||
// @pymethod |Py{interfacename}|{method}|Description of {method}.
|
||||
PyObject *Py{interfacename}::{method}(PyObject *self, PyObject *args)
|
||||
{{
|
||||
{interfacename} *p{ptr} = GetI(self);
|
||||
if ( p{ptr} == NULL )
|
||||
return NULL;
|
||||
""".format(**strdict)
|
||||
)
|
||||
argsParseTuple = argsCOM = formatChars = codePost = codePobjects = (
|
||||
codeCobjects
|
||||
) = cleanup = cleanup_gil = ""
|
||||
needConversion = 0
|
||||
# if method.name=="Stat": import win32dbg;win32dbg.brk()
|
||||
for arg in method.args:
|
||||
try:
|
||||
argCvt = makegwparse.make_arg_converter(arg)
|
||||
if arg.HasAttribute("in"):
|
||||
val = argCvt.GetFormatChar()
|
||||
if val:
|
||||
f.write("\t" + argCvt.GetAutoduckString() + "\n")
|
||||
formatChars += val
|
||||
argsParseTuple += ", " + argCvt.GetParseTupleArg()
|
||||
codePobjects += argCvt.DeclareParseArgTupleInputConverter()
|
||||
codePost += argCvt.GetParsePostCode()
|
||||
needConversion = needConversion or argCvt.NeedUSES_CONVERSION()
|
||||
cleanup += argCvt.GetInterfaceArgCleanup()
|
||||
cleanup_gil += argCvt.GetInterfaceArgCleanupGIL()
|
||||
comArgName, comArgDeclString = argCvt.GetInterfaceCppObjectInfo()
|
||||
if comArgDeclString: # If we should declare a variable
|
||||
codeCobjects += "\t%s;\n" % comArgDeclString
|
||||
argsCOM += ", " + comArgName
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write(
|
||||
'// *** The input argument {} of type "{}" was not processed ***\n// Please check the conversion function is appropriate and exists!\n'.format(
|
||||
arg.name, arg.raw_type
|
||||
)
|
||||
)
|
||||
|
||||
f.write(f"\t{arg.type} {arg.name};\n\tPyObject *ob{arg.name};\n")
|
||||
f.write(
|
||||
"\t// @pyparm <o Py{}>|{}||Description for {}\n".format(
|
||||
arg.type, arg.name, arg.name
|
||||
)
|
||||
)
|
||||
codePost += "\tif (bPythonIsHappy && !PyObject_As{}( ob{}, &{} )) bPythonIsHappy = FALSE;\n".format(
|
||||
arg.type, arg.name, arg.name
|
||||
)
|
||||
|
||||
formatChars += "O"
|
||||
argsParseTuple += ", &ob%s" % arg.name
|
||||
|
||||
argsCOM += ", " + arg.name
|
||||
cleanup += f"\tPyObject_Free{arg.type}({arg.name});\n"
|
||||
|
||||
if needConversion:
|
||||
f.write("\tUSES_CONVERSION;\n")
|
||||
f.write(codePobjects)
|
||||
f.write(codeCobjects)
|
||||
f.write(
|
||||
'\tif ( !PyArg_ParseTuple(args, "{}:{}"{}) )\n\t\treturn NULL;\n'.format(
|
||||
formatChars, method.name, argsParseTuple
|
||||
)
|
||||
)
|
||||
if codePost:
|
||||
f.write("\tBOOL bPythonIsHappy = TRUE;\n")
|
||||
f.write(codePost)
|
||||
f.write("\tif (!bPythonIsHappy) return NULL;\n")
|
||||
strdict["argsCOM"] = argsCOM[1:]
|
||||
strdict["cleanup"] = cleanup
|
||||
strdict["cleanup_gil"] = cleanup_gil
|
||||
f.write(
|
||||
""" HRESULT hr;
|
||||
PY_INTERFACE_PRECALL;
|
||||
hr = p{ptr}->{method}({argsCOM} );
|
||||
{cleanup}
|
||||
PY_INTERFACE_POSTCALL;
|
||||
{cleanup_gil}
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, p{ptr}, IID_{interfacename} );
|
||||
""".format(**strdict)
|
||||
)
|
||||
codePre = codePost = formatChars = codeVarsPass = codeDecl = ""
|
||||
for arg in method.args:
|
||||
if not arg.HasAttribute("out"):
|
||||
continue
|
||||
try:
|
||||
argCvt = makegwparse.make_arg_converter(arg)
|
||||
formatChar = argCvt.GetFormatChar()
|
||||
if formatChar:
|
||||
formatChars += formatChar
|
||||
codePre += argCvt.GetBuildForInterfacePreCode()
|
||||
codePost += argCvt.GetBuildForInterfacePostCode()
|
||||
codeVarsPass += ", " + argCvt.GetBuildValueArg()
|
||||
codeDecl += argCvt.DeclareParseArgTupleInputConverter()
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write(
|
||||
'// *** The output argument {} of type "{}" was not processed ***\n// {}\n'.format(
|
||||
arg.name, arg.raw_type, why
|
||||
)
|
||||
)
|
||||
continue
|
||||
if formatChars:
|
||||
f.write(
|
||||
'{}\n{}\tPyObject *pyretval = Py_BuildValue("{}"{});\n{}\treturn pyretval;'.format(
|
||||
codeDecl, codePre, formatChars, codeVarsPass, codePost
|
||||
)
|
||||
)
|
||||
else:
|
||||
f.write("\tPy_RETURN_NONE;\n")
|
||||
f.write("\n}\n\n")
|
||||
|
||||
f.write("// @object Py%s|Description of the interface\n" % (name))
|
||||
f.write("static struct PyMethodDef Py%s_methods[] =\n{\n" % name)
|
||||
for method in interface.methods:
|
||||
f.write(
|
||||
'\t{{ "{}", Py{}::{}, 1 }}, // @pymeth {}|Description of {}\n'.format(
|
||||
method.name, interface.name, method.name, method.name, method.name
|
||||
)
|
||||
)
|
||||
|
||||
interfacebase = interface.base
|
||||
f.write(
|
||||
"""\
|
||||
{{ NULL }}
|
||||
}};
|
||||
|
||||
PyComTypeObject Py{name}::type("Py{name}",
|
||||
&Py{interfacebase}::type,
|
||||
sizeof(Py{name}),
|
||||
Py{name}_methods,
|
||||
GET_PYCOM_CTOR(Py{name}));
|
||||
""".format(**locals())
|
||||
)
|
||||
|
||||
|
||||
def _write_gw_h(f, interface):
|
||||
if interface.name[0] == "I":
|
||||
gname = "PyG" + interface.name[1:]
|
||||
else:
|
||||
gname = "PyG" + interface.name
|
||||
name = interface.name
|
||||
if interface.base == "IUnknown" or interface.base == "IDispatch":
|
||||
base_name = "PyGatewayBase"
|
||||
else:
|
||||
if interface.base[0] == "I":
|
||||
base_name = "PyG" + interface.base[1:]
|
||||
else:
|
||||
base_name = "PyG" + interface.base
|
||||
f.write(
|
||||
f"""\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Gateway Declaration
|
||||
|
||||
class {gname} : public {base_name}, public {name}
|
||||
{{
|
||||
protected:
|
||||
{gname}(PyObject *instance) : {base_name}(instance) {{ ; }}
|
||||
PYGATEWAY_MAKE_SUPPORT2({gname}, {name}, IID_{name}, {base_name})
|
||||
|
||||
"""
|
||||
)
|
||||
if interface.base != "IUnknown":
|
||||
f.write(
|
||||
"\t// {}\n\t// *** Manually add {} method decls here\n\n".format(
|
||||
interface.base, interface.base
|
||||
)
|
||||
)
|
||||
else:
|
||||
f.write("\n\n")
|
||||
|
||||
f.write("\t// %s\n" % name)
|
||||
|
||||
for method in interface.methods:
|
||||
f.write("\tSTDMETHOD(%s)(\n" % method.name)
|
||||
if method.args:
|
||||
for arg in method.args[:-1]:
|
||||
f.write("\t\t%s,\n" % (arg.GetRawDeclaration()))
|
||||
arg = method.args[-1]
|
||||
f.write("\t\t%s);\n\n" % (arg.GetRawDeclaration()))
|
||||
else:
|
||||
f.write("\t\tvoid);\n\n")
|
||||
|
||||
f.write("};\n")
|
||||
f.close()
|
||||
|
||||
|
||||
def _write_gw_cpp(f, interface):
|
||||
if interface.name[0] == "I":
|
||||
gname = "PyG" + interface.name[1:]
|
||||
else:
|
||||
gname = "PyG" + interface.name
|
||||
name = interface.name
|
||||
if interface.base == "IUnknown" or interface.base == "IDispatch":
|
||||
base_name = "PyGatewayBase"
|
||||
else:
|
||||
if interface.base[0] == "I":
|
||||
base_name = "PyG" + interface.base[1:]
|
||||
else:
|
||||
base_name = "PyG" + interface.base
|
||||
f.write(
|
||||
"""\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Gateway Implementation
|
||||
"""
|
||||
)
|
||||
|
||||
for method in interface.methods:
|
||||
f.write(
|
||||
f"""\
|
||||
STDMETHODIMP {gname}::{method.name}(
|
||||
"""
|
||||
)
|
||||
|
||||
if method.args:
|
||||
for arg in method.args[:-1]:
|
||||
inoutstr = "][".join(arg.inout)
|
||||
f.write(f"\t\t/* [{inoutstr}] */ {arg.GetRawDeclaration()},\n")
|
||||
|
||||
arg = method.args[-1]
|
||||
inoutstr = "][".join(arg.inout)
|
||||
f.write(f"\t\t/* [{inoutstr}] */ {arg.GetRawDeclaration()})\n")
|
||||
else:
|
||||
f.write("\t\tvoid)\n")
|
||||
|
||||
f.write("{\n\tPY_GATEWAY_METHOD;\n")
|
||||
cout = 0
|
||||
codePre = codePost = codeVars = ""
|
||||
argStr = ""
|
||||
needConversion = 0
|
||||
formatChars = ""
|
||||
if method.args:
|
||||
for arg in method.args:
|
||||
if arg.HasAttribute("out"):
|
||||
cout += 1
|
||||
if arg.indirectionLevel == 2:
|
||||
f.write("\tif (%s==NULL) return E_POINTER;\n" % arg.name)
|
||||
if arg.HasAttribute("in"):
|
||||
try:
|
||||
argCvt = makegwparse.make_arg_converter(arg)
|
||||
argCvt.SetGatewayMode()
|
||||
formatchar = argCvt.GetFormatChar()
|
||||
needConversion = needConversion or argCvt.NeedUSES_CONVERSION()
|
||||
|
||||
if formatchar:
|
||||
formatChars += formatchar
|
||||
codeVars += argCvt.DeclareParseArgTupleInputConverter()
|
||||
argStr += ", " + argCvt.GetBuildValueArg()
|
||||
codePre += argCvt.GetBuildForGatewayPreCode()
|
||||
codePost += argCvt.GetBuildForGatewayPostCode()
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write(
|
||||
'// *** The input argument {} of type "{}" was not processed ***\n// - Please ensure this conversion function exists, and is appropriate\n// - {}\n'.format(
|
||||
arg.name, arg.raw_type, why
|
||||
)
|
||||
)
|
||||
f.write(
|
||||
"\tPyObject *ob{} = PyObject_From{}({});\n".format(
|
||||
arg.name, arg.type, arg.name
|
||||
)
|
||||
)
|
||||
f.write(
|
||||
'\tif (ob{}==NULL) return MAKE_PYCOM_GATEWAY_FAILURE_CODE("{}");\n'.format(
|
||||
arg.name, method.name
|
||||
)
|
||||
)
|
||||
codePost += "\tPy_DECREF(ob%s);\n" % arg.name
|
||||
formatChars += "O"
|
||||
argStr += ", ob%s" % arg.name
|
||||
|
||||
if needConversion:
|
||||
f.write("\tUSES_CONVERSION;\n")
|
||||
f.write(codeVars)
|
||||
f.write(codePre)
|
||||
if cout:
|
||||
f.write("\tPyObject *result;\n")
|
||||
resStr = "&result"
|
||||
else:
|
||||
resStr = "NULL"
|
||||
|
||||
if formatChars:
|
||||
fullArgStr = f'{resStr}, "{formatChars}"{argStr}'
|
||||
else:
|
||||
fullArgStr = resStr
|
||||
|
||||
f.write(f'\tHRESULT hr=InvokeViaPolicy("{method.name}", {fullArgStr});\n')
|
||||
f.write(codePost)
|
||||
if cout:
|
||||
f.write("\tif (FAILED(hr)) return hr;\n")
|
||||
f.write(
|
||||
"\t// Process the Python results, and convert back to the real params\n"
|
||||
)
|
||||
# process the output arguments.
|
||||
formatChars = codePobjects = codePost = argsParseTuple = ""
|
||||
needConversion = 0
|
||||
for arg in method.args:
|
||||
if not arg.HasAttribute("out"):
|
||||
continue
|
||||
try:
|
||||
argCvt = makegwparse.make_arg_converter(arg)
|
||||
argCvt.SetGatewayMode()
|
||||
val = argCvt.GetFormatChar()
|
||||
if val:
|
||||
formatChars += val
|
||||
argsParseTuple += ", " + argCvt.GetParseTupleArg()
|
||||
codePobjects += argCvt.DeclareParseArgTupleInputConverter()
|
||||
codePost += argCvt.GetParsePostCode()
|
||||
needConversion = needConversion or argCvt.NeedUSES_CONVERSION()
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write(
|
||||
'// *** The output argument {} of type "{}" was not processed ***\n// {}\n'.format(
|
||||
arg.name, arg.raw_type, why
|
||||
)
|
||||
)
|
||||
|
||||
if formatChars: # If I have any to actually process.
|
||||
if len(formatChars) == 1:
|
||||
parseFn = "PyArg_Parse"
|
||||
else:
|
||||
parseFn = "PyArg_ParseTuple"
|
||||
if codePobjects:
|
||||
f.write(codePobjects)
|
||||
f.write(
|
||||
'\tif (!{}(result, "{}" {}))\n\t\treturn MAKE_PYCOM_GATEWAY_FAILURE_CODE("{}");\n'.format(
|
||||
parseFn, formatChars, argsParseTuple, method.name
|
||||
)
|
||||
)
|
||||
if codePost:
|
||||
f.write("\tBOOL bPythonIsHappy = TRUE;\n")
|
||||
f.write(codePost)
|
||||
f.write(
|
||||
'\tif (!bPythonIsHappy) hr = MAKE_PYCOM_GATEWAY_FAILURE_CODE("%s");\n'
|
||||
% method.name
|
||||
)
|
||||
f.write("\tPy_DECREF(result);\n")
|
||||
f.write("\treturn hr;\n}\n\n")
|
||||
|
||||
|
||||
def test():
|
||||
# make_framework_support("d:\\msdev\\include\\objidl.h", "ILockBytes")
|
||||
make_framework_support("d:\\msdev\\include\\objidl.h", "IStorage")
|
||||
|
||||
|
||||
# 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,
|
||||
)
|
||||
@@ -0,0 +1,331 @@
|
||||
"""Utility file for generating PyIEnum support.
|
||||
|
||||
This is almost a 'template' file. It simplay contains almost full
|
||||
C++ source code for PyIEnum* support, and the Python code simply
|
||||
substitutes the appropriate interface name.
|
||||
|
||||
This module is notmally not used directly - the @makegw@ module
|
||||
automatically calls this.
|
||||
"""
|
||||
|
||||
#
|
||||
# INTERNAL FUNCTIONS
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
def is_interface_enum(enumtype):
|
||||
return not (enumtype[0].isupper() and enumtype[2].isupper())
|
||||
|
||||
|
||||
def _write_enumifc_cpp(f, interface):
|
||||
enumtype = interface.name[5:]
|
||||
if is_interface_enum(enumtype):
|
||||
# Assume an interface.
|
||||
enum_interface = "I" + enumtype[:-1]
|
||||
converter = "PyObject *ob = PyCom_PyObjectFromIUnknown(rgVar[i], IID_{enum_interface}, FALSE);".format(
|
||||
**locals()
|
||||
)
|
||||
arraydeclare = (
|
||||
"{enum_interface} **rgVar = new {enum_interface} *[celt];".format(
|
||||
**locals()
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Enum of a simple structure
|
||||
converter = "PyObject *ob = PyCom_PyObjectFrom{enumtype}(&rgVar[i]);".format(
|
||||
**locals()
|
||||
)
|
||||
arraydeclare = "{enumtype} *rgVar = new {enumtype}[celt];".format(**locals())
|
||||
|
||||
f.write(
|
||||
"""
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Interface Implementation
|
||||
|
||||
PyIEnum{enumtype}::PyIEnum{enumtype}(IUnknown *pdisp):
|
||||
PyIUnknown(pdisp)
|
||||
{{
|
||||
ob_type = &type;
|
||||
}}
|
||||
|
||||
PyIEnum{enumtype}::~PyIEnum{enumtype}()
|
||||
{{
|
||||
}}
|
||||
|
||||
/* static */ IEnum{enumtype} *PyIEnum{enumtype}::GetI(PyObject *self)
|
||||
{{
|
||||
return (IEnum{enumtype} *)PyIUnknown::GetI(self);
|
||||
}}
|
||||
|
||||
// @pymethod object|PyIEnum{enumtype}|Next|Retrieves a specified number of items in the enumeration sequence.
|
||||
PyObject *PyIEnum{enumtype}::Next(PyObject *self, PyObject *args)
|
||||
{{
|
||||
long celt = 1;
|
||||
// @pyparm int|num|1|Number of items to retrieve.
|
||||
if ( !PyArg_ParseTuple(args, "|l:Next", &celt) )
|
||||
return NULL;
|
||||
|
||||
IEnum{enumtype} *pIE{enumtype} = GetI(self);
|
||||
if ( pIE{enumtype} == NULL )
|
||||
return NULL;
|
||||
|
||||
{arraydeclare}
|
||||
if ( rgVar == NULL ) {{
|
||||
PyErr_SetString(PyExc_MemoryError, "allocating result {enumtype}s");
|
||||
return NULL;
|
||||
}}
|
||||
|
||||
int i;
|
||||
/* for ( i = celt; i--; )
|
||||
// *** possibly init each structure element???
|
||||
*/
|
||||
|
||||
ULONG celtFetched = 0;
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE{enumtype}->Next(celt, rgVar, &celtFetched);
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( HRESULT_CODE(hr) != ERROR_NO_MORE_ITEMS && FAILED(hr) )
|
||||
{{
|
||||
delete [] rgVar;
|
||||
return PyCom_BuildPyException(hr,pIE{enumtype}, IID_IE{enumtype});
|
||||
}}
|
||||
|
||||
PyObject *result = PyTuple_New(celtFetched);
|
||||
if ( result != NULL )
|
||||
{{
|
||||
for ( i = celtFetched; i--; )
|
||||
{{
|
||||
{converter}
|
||||
if ( ob == NULL )
|
||||
{{
|
||||
Py_DECREF(result);
|
||||
result = NULL;
|
||||
break;
|
||||
}}
|
||||
PyTuple_SET_ITEM(result, i, ob);
|
||||
}}
|
||||
}}
|
||||
|
||||
/* for ( i = celtFetched; i--; )
|
||||
// *** possibly cleanup each structure element???
|
||||
*/
|
||||
delete [] rgVar;
|
||||
return result;
|
||||
}}
|
||||
|
||||
// @pymethod |PyIEnum{enumtype}|Skip|Skips over the next specified elementes.
|
||||
PyObject *PyIEnum{enumtype}::Skip(PyObject *self, PyObject *args)
|
||||
{{
|
||||
long celt;
|
||||
if ( !PyArg_ParseTuple(args, "l:Skip", &celt) )
|
||||
return NULL;
|
||||
|
||||
IEnum{enumtype} *pIE{enumtype} = GetI(self);
|
||||
if ( pIE{enumtype} == NULL )
|
||||
return NULL;
|
||||
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE{enumtype}->Skip(celt);
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, pIE{enumtype}, IID_IE{enumtype});
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}}
|
||||
|
||||
// @pymethod |PyIEnum{enumtype}|Reset|Resets the enumeration sequence to the beginning.
|
||||
PyObject *PyIEnum{enumtype}::Reset(PyObject *self, PyObject *args)
|
||||
{{
|
||||
if ( !PyArg_ParseTuple(args, ":Reset") )
|
||||
return NULL;
|
||||
|
||||
IEnum{enumtype} *pIE{enumtype} = GetI(self);
|
||||
if ( pIE{enumtype} == NULL )
|
||||
return NULL;
|
||||
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE{enumtype}->Reset();
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, pIE{enumtype}, IID_IE{enumtype});
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}}
|
||||
|
||||
// @pymethod <o PyIEnum{enumtype}>|PyIEnum{enumtype}|Clone|Creates another enumerator that contains the same enumeration state as the current one
|
||||
PyObject *PyIEnum{enumtype}::Clone(PyObject *self, PyObject *args)
|
||||
{{
|
||||
if ( !PyArg_ParseTuple(args, ":Clone") )
|
||||
return NULL;
|
||||
|
||||
IEnum{enumtype} *pIE{enumtype} = GetI(self);
|
||||
if ( pIE{enumtype} == NULL )
|
||||
return NULL;
|
||||
|
||||
IEnum{enumtype} *pClone;
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE{enumtype}->Clone(&pClone);
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, pIE{enumtype}, IID_IE{enumtype});
|
||||
|
||||
return PyCom_PyObjectFromIUnknown(pClone, IID_IEnum{enumtype}, FALSE);
|
||||
}}
|
||||
|
||||
// @object PyIEnum{enumtype}|A Python interface to IEnum{enumtype}
|
||||
static struct PyMethodDef PyIEnum{enumtype}_methods[] =
|
||||
{{
|
||||
{{ "Next", PyIEnum{enumtype}::Next, 1 }}, // @pymeth Next|Retrieves a specified number of items in the enumeration sequence.
|
||||
{{ "Skip", PyIEnum{enumtype}::Skip, 1 }}, // @pymeth Skip|Skips over the next specified elementes.
|
||||
{{ "Reset", PyIEnum{enumtype}::Reset, 1 }}, // @pymeth Reset|Resets the enumeration sequence to the beginning.
|
||||
{{ "Clone", PyIEnum{enumtype}::Clone, 1 }}, // @pymeth Clone|Creates another enumerator that contains the same enumeration state as the current one.
|
||||
{{ NULL }}
|
||||
}};
|
||||
|
||||
PyComEnumTypeObject PyIEnum{enumtype}::type("PyIEnum{enumtype}",
|
||||
&PyIUnknown::type,
|
||||
sizeof(PyIEnum{enumtype}),
|
||||
PyIEnum{enumtype}_methods,
|
||||
GET_PYCOM_CTOR(PyIEnum{enumtype}));
|
||||
""".format(**locals())
|
||||
)
|
||||
|
||||
|
||||
def _write_enumgw_cpp(f, interface):
|
||||
enumtype = interface.name[5:]
|
||||
if is_interface_enum(enumtype):
|
||||
# Assume an interface.
|
||||
enum_interface = "I" + enumtype[:-1]
|
||||
converter = "if ( !PyCom_InterfaceFromPyObject(ob, IID_{enum_interface}, (void **)&rgVar[i], FALSE) )".format(
|
||||
**locals()
|
||||
)
|
||||
argdeclare = "{enum_interface} __RPC_FAR * __RPC_FAR *rgVar".format(**locals())
|
||||
else:
|
||||
argdeclare = "{enumtype} __RPC_FAR *rgVar".format(**locals())
|
||||
converter = "if ( !PyCom_PyObjectAs{enumtype}(ob, &rgVar[i]) )".format(
|
||||
**locals()
|
||||
)
|
||||
f.write(
|
||||
"""
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Gateway Implementation
|
||||
|
||||
// Std delegation
|
||||
STDMETHODIMP_(ULONG) PyGEnum{enumtype}::AddRef(void) {{return PyGatewayBase::AddRef();}}
|
||||
STDMETHODIMP_(ULONG) PyGEnum{enumtype}::Release(void) {{return PyGatewayBase::Release();}}
|
||||
STDMETHODIMP PyGEnum{enumtype}::QueryInterface(REFIID iid, void ** obj) {{return PyGatewayBase::QueryInterface(iid, obj);}}
|
||||
STDMETHODIMP PyGEnum{enumtype}::GetTypeInfoCount(UINT FAR* pctInfo) {{return PyGatewayBase::GetTypeInfoCount(pctInfo);}}
|
||||
STDMETHODIMP PyGEnum{enumtype}::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptInfo) {{return PyGatewayBase::GetTypeInfo(itinfo, lcid, pptInfo);}}
|
||||
STDMETHODIMP PyGEnum{enumtype}::GetIDsOfNames(REFIID refiid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid) {{return PyGatewayBase::GetIDsOfNames( refiid, rgszNames, cNames, lcid, rgdispid);}}
|
||||
STDMETHODIMP PyGEnum{enumtype}::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* params, VARIANT FAR* pVarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr) {{return PyGatewayBase::Invoke( dispid, riid, lcid, wFlags, params, pVarResult, pexcepinfo, puArgErr);}}
|
||||
|
||||
STDMETHODIMP PyGEnum{enumtype}::Next(
|
||||
/* [in] */ ULONG celt,
|
||||
/* [length_is][size_is][out] */ {argdeclare},
|
||||
/* [out] */ ULONG __RPC_FAR *pCeltFetched)
|
||||
{{
|
||||
PY_GATEWAY_METHOD;
|
||||
PyObject *result;
|
||||
HRESULT hr = InvokeViaPolicy("Next", &result, "i", celt);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
if ( !PySequence_Check(result) )
|
||||
goto error;
|
||||
int len;
|
||||
len = PyObject_Length(result);
|
||||
if ( len == -1 )
|
||||
goto error;
|
||||
if ( len > (int)celt)
|
||||
len = celt;
|
||||
|
||||
if ( pCeltFetched )
|
||||
*pCeltFetched = len;
|
||||
|
||||
int i;
|
||||
for ( i = 0; i < len; ++i )
|
||||
{{
|
||||
PyObject *ob = PySequence_GetItem(result, i);
|
||||
if ( ob == NULL )
|
||||
goto error;
|
||||
|
||||
{converter}
|
||||
{{
|
||||
Py_DECREF(result);
|
||||
return PyCom_SetCOMErrorFromPyException(IID_IEnum{enumtype});
|
||||
}}
|
||||
}}
|
||||
|
||||
Py_DECREF(result);
|
||||
|
||||
return len < (int)celt ? S_FALSE : S_OK;
|
||||
|
||||
error:
|
||||
PyErr_Clear(); // just in case
|
||||
Py_DECREF(result);
|
||||
return PyCom_HandleIEnumNoSequence(IID_IEnum{enumtype});
|
||||
}}
|
||||
|
||||
STDMETHODIMP PyGEnum{enumtype}::Skip(
|
||||
/* [in] */ ULONG celt)
|
||||
{{
|
||||
PY_GATEWAY_METHOD;
|
||||
return InvokeViaPolicy("Skip", NULL, "i", celt);
|
||||
}}
|
||||
|
||||
STDMETHODIMP PyGEnum{enumtype}::Reset(void)
|
||||
{{
|
||||
PY_GATEWAY_METHOD;
|
||||
return InvokeViaPolicy("Reset");
|
||||
}}
|
||||
|
||||
STDMETHODIMP PyGEnum{enumtype}::Clone(
|
||||
/* [out] */ IEnum{enumtype} __RPC_FAR *__RPC_FAR *ppEnum)
|
||||
{{
|
||||
PY_GATEWAY_METHOD;
|
||||
PyObject * result;
|
||||
HRESULT hr = InvokeViaPolicy("Clone", &result);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
/*
|
||||
** Make sure we have the right kind of object: we should have some kind
|
||||
** of IUnknown subclass wrapped into a PyIUnknown instance.
|
||||
*/
|
||||
if ( !PyIBase::is_object(result, &PyIUnknown::type) )
|
||||
{{
|
||||
/* the wrong kind of object was returned to us */
|
||||
Py_DECREF(result);
|
||||
return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum{enumtype});
|
||||
}}
|
||||
|
||||
/*
|
||||
** Get the IUnknown out of the thing. note that the Python ob maintains
|
||||
** a reference, so we don't have to explicitly AddRef() here.
|
||||
*/
|
||||
IUnknown *punk = ((PyIUnknown *)result)->m_obj;
|
||||
if ( !punk )
|
||||
{{
|
||||
/* damn. the object was released. */
|
||||
Py_DECREF(result);
|
||||
return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum{enumtype});
|
||||
}}
|
||||
|
||||
/*
|
||||
** Get the interface we want. note it is returned with a refcount.
|
||||
** This QI is actually going to instantiate a PyGEnum{enumtype}.
|
||||
*/
|
||||
hr = punk->QueryInterface(IID_IEnum{enumtype}, (LPVOID *)ppEnum);
|
||||
|
||||
/* done with the result; this DECREF is also for <punk> */
|
||||
Py_DECREF(result);
|
||||
|
||||
return PyCom_CheckIEnumNextResult(hr, IID_IEnum{enumtype});
|
||||
}}
|
||||
""".format(**locals())
|
||||
)
|
||||
1017
Utils/PythonNew32/Lib/site-packages/win32com/makegw/makegwparse.py
Normal file
1017
Utils/PythonNew32/Lib/site-packages/win32com/makegw/makegwparse.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user