Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
1
venv/Lib/site-packages/win32com/makegw/__init__.py
Normal file
1
venv/Lib/site-packages/win32com/makegw/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
# indicates a python package.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
451
venv/Lib/site-packages/win32com/makegw/makegw.py
Normal file
451
venv/Lib/site-packages/win32com/makegw/makegw.py
Normal file
|
@ -0,0 +1,451 @@
|
|||
"""Utility functions for writing out gateway C++ files
|
||||
|
||||
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.
|
||||
|
||||
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 re
|
||||
from . import makegwparse
|
||||
|
||||
def make_framework_support(header_file_name, interface_name, bMakeInterface = 1, bMakeGateway = 1):
|
||||
"""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("Py%s.cpp" % interface.name, "w")
|
||||
try:
|
||||
fout.write(\
|
||||
'''\
|
||||
// This file implements the %s %s for Python.
|
||||
// Generated by makegw.py
|
||||
|
||||
#include "shell_pch.h"
|
||||
''' % (interface.name, desc))
|
||||
# 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("Py%s.h" % interface.name, "w")
|
||||
try:
|
||||
fout.write(\
|
||||
'''\
|
||||
// This file declares the %s %s for Python.
|
||||
// Generated by makegw.py
|
||||
''' % (interface.name, desc))
|
||||
|
||||
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(\
|
||||
'''\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Interface Declaration
|
||||
|
||||
class Py%s : public Py%s
|
||||
{
|
||||
public:
|
||||
MAKE_PYCOM_CTOR(Py%s);
|
||||
static %s *GetI(PyObject *self);
|
||||
static PyComTypeObject type;
|
||||
|
||||
// The Python methods
|
||||
''' % (interface.name, interface.base, interface.name, interface.name))
|
||||
for method in interface.methods:
|
||||
f.write('\tstatic PyObject *%s(PyObject *self, PyObject *args);\n' % method.name)
|
||||
f.write(\
|
||||
'''\
|
||||
|
||||
protected:
|
||||
Py%s(IUnknown *pdisp);
|
||||
~Py%s();
|
||||
};
|
||||
''' % (interface.name, interface.name))
|
||||
|
||||
def _write_ifc_cpp(f, interface):
|
||||
name = interface.name
|
||||
f.write(\
|
||||
'''\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Interface Implementation
|
||||
|
||||
Py%(name)s::Py%(name)s(IUnknown *pdisp):
|
||||
Py%(base)s(pdisp)
|
||||
{
|
||||
ob_type = &type;
|
||||
}
|
||||
|
||||
Py%(name)s::~Py%(name)s()
|
||||
{
|
||||
}
|
||||
|
||||
/* static */ %(name)s *Py%(name)s::GetI(PyObject *self)
|
||||
{
|
||||
return (%(name)s *)Py%(base)s::GetI(self);
|
||||
}
|
||||
|
||||
''' % (interface.__dict__))
|
||||
|
||||
ptr = re.sub('[a-z]', '', interface.name)
|
||||
strdict = {'interfacename':interface.name, 'ptr': ptr}
|
||||
for method in interface.methods:
|
||||
strdict['method'] = method.name
|
||||
f.write(\
|
||||
'''\
|
||||
// @pymethod |Py%(interfacename)s|%(method)s|Description of %(method)s.
|
||||
PyObject *Py%(interfacename)s::%(method)s(PyObject *self, PyObject *args)
|
||||
{
|
||||
%(interfacename)s *p%(ptr)s = GetI(self);
|
||||
if ( p%(ptr)s == NULL )
|
||||
return NULL;
|
||||
''' % 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 = formatChars + val
|
||||
argsParseTuple = argsParseTuple + ", " + argCvt.GetParseTupleArg()
|
||||
codePobjects = codePobjects + argCvt.DeclareParseArgTupleInputConverter()
|
||||
codePost = codePost + argCvt.GetParsePostCode()
|
||||
needConversion = needConversion or argCvt.NeedUSES_CONVERSION()
|
||||
cleanup = cleanup + argCvt.GetInterfaceArgCleanup()
|
||||
cleanup_gil = cleanup_gil + argCvt.GetInterfaceArgCleanupGIL()
|
||||
comArgName, comArgDeclString = argCvt.GetInterfaceCppObjectInfo()
|
||||
if comArgDeclString: # If we should declare a variable
|
||||
codeCobjects = codeCobjects + "\t%s;\n" % (comArgDeclString)
|
||||
argsCOM = argsCOM + ", " + comArgName
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write('// *** The input argument %s of type "%s" was not processed ***\n// Please check the conversion function is appropriate and exists!\n' % (arg.name, arg.raw_type))
|
||||
|
||||
f.write('\t%s %s;\n\tPyObject *ob%s;\n' % (arg.type, arg.name, arg.name))
|
||||
f.write('\t// @pyparm <o Py%s>|%s||Description for %s\n' % (arg.type, arg.name, arg.name))
|
||||
codePost = codePost + '\tif (bPythonIsHappy && !PyObject_As%s( ob%s, &%s )) bPythonIsHappy = FALSE;\n' % (arg.type, arg.name, arg.name)
|
||||
|
||||
formatChars = formatChars + "O"
|
||||
argsParseTuple = argsParseTuple + ", &ob%s" % (arg.name)
|
||||
|
||||
argsCOM = argsCOM + ", " + arg.name
|
||||
cleanup = cleanup + "\tPyObject_Free%s(%s);\n" % (arg.type, arg.name)
|
||||
|
||||
if needConversion: f.write("\tUSES_CONVERSION;\n")
|
||||
f.write(codePobjects);
|
||||
f.write(codeCobjects);
|
||||
f.write('\tif ( !PyArg_ParseTuple(args, "%s:%s"%s) )\n\t\treturn NULL;\n' % (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)s->%(method)s(%(argsCOM)s );
|
||||
%(cleanup)s
|
||||
PY_INTERFACE_POSTCALL;
|
||||
%(cleanup_gil)s
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, p%(ptr)s, IID_%(interfacename)s );
|
||||
''' % 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 = formatChars + formatChar
|
||||
codePre = codePre + argCvt.GetBuildForInterfacePreCode()
|
||||
codePost = codePost + argCvt.GetBuildForInterfacePostCode()
|
||||
codeVarsPass = codeVarsPass + ", " + argCvt.GetBuildValueArg()
|
||||
codeDecl = codeDecl + argCvt.DeclareParseArgTupleInputConverter()
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write('// *** The output argument %s of type "%s" was not processed ***\n// %s\n' % (arg.name, arg.raw_type, why))
|
||||
continue
|
||||
if formatChars:
|
||||
f.write('%s\n%s\tPyObject *pyretval = Py_BuildValue("%s"%s);\n%s\treturn pyretval;' % (codeDecl, codePre, formatChars, codeVarsPass, codePost))
|
||||
else:
|
||||
f.write('\tPy_INCREF(Py_None);\n\treturn Py_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{ "%s", Py%s::%s, 1 }, // @pymeth %s|Description of %s\n' % (method.name, interface.name, method.name, method.name, method.name))
|
||||
|
||||
interfacebase = interface.base
|
||||
f.write('''\
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
PyComTypeObject Py%(name)s::type("Py%(name)s",
|
||||
&Py%(interfacebase)s::type,
|
||||
sizeof(Py%(name)s),
|
||||
Py%(name)s_methods,
|
||||
GET_PYCOM_CTOR(Py%(name)s));
|
||||
''' % 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(\
|
||||
'''\
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Gateway Declaration
|
||||
|
||||
class %s : public %s, public %s
|
||||
{
|
||||
protected:
|
||||
%s(PyObject *instance) : %s(instance) { ; }
|
||||
PYGATEWAY_MAKE_SUPPORT2(%s, %s, IID_%s, %s)
|
||||
|
||||
''' % (gname, base_name, name, gname, base_name, gname, name, name, base_name))
|
||||
if interface.base != "IUnknown":
|
||||
f.write("\t// %s\n\t// *** Manually add %s method decls here\n\n" % (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
|
||||
''' % {'name':name, 'gname':gname, 'base_name':base_name})
|
||||
|
||||
for method in interface.methods:
|
||||
f.write(\
|
||||
'''\
|
||||
STDMETHODIMP %s::%s(
|
||||
''' % (gname, method.name))
|
||||
|
||||
if method.args:
|
||||
for arg in method.args[:-1]:
|
||||
inoutstr = ']['.join(arg.inout)
|
||||
f.write("\t\t/* [%s] */ %s,\n" % (inoutstr, arg.GetRawDeclaration()))
|
||||
|
||||
arg = method.args[-1]
|
||||
inoutstr = ']['.join(arg.inout)
|
||||
f.write("\t\t/* [%s] */ %s)\n" % (inoutstr, arg.GetRawDeclaration()))
|
||||
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 = 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 = formatChars + formatchar
|
||||
codeVars = codeVars + argCvt.DeclareParseArgTupleInputConverter()
|
||||
argStr = argStr + ", " + argCvt.GetBuildValueArg()
|
||||
codePre = codePre + argCvt.GetBuildForGatewayPreCode()
|
||||
codePost = codePost + argCvt.GetBuildForGatewayPostCode()
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write('// *** The input argument %s of type "%s" was not processed ***\n// - Please ensure this conversion function exists, and is appropriate\n// - %s\n' % (arg.name, arg.raw_type, why))
|
||||
f.write('\tPyObject *ob%s = PyObject_From%s(%s);\n' % (arg.name, arg.type, arg.name))
|
||||
f.write('\tif (ob%s==NULL) return MAKE_PYCOM_GATEWAY_FAILURE_CODE("%s");\n' % (arg.name, method.name))
|
||||
codePost = codePost + "\tPy_DECREF(ob%s);\n" % arg.name
|
||||
formatChars = formatChars + "O"
|
||||
argStr = 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 = '%s, "%s"%s' % (resStr, formatChars, argStr)
|
||||
else:
|
||||
fullArgStr = resStr
|
||||
|
||||
f.write('\tHRESULT hr=InvokeViaPolicy("%s", %s);\n' % (method.name, fullArgStr))
|
||||
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 = formatChars + val
|
||||
argsParseTuple = argsParseTuple + ", " + argCvt.GetParseTupleArg()
|
||||
codePobjects = codePobjects + argCvt.DeclareParseArgTupleInputConverter()
|
||||
codePost = codePost + argCvt.GetParsePostCode()
|
||||
needConversion = needConversion or argCvt.NeedUSES_CONVERSION()
|
||||
except makegwparse.error_not_supported as why:
|
||||
f.write('// *** The output argument %s of type "%s" was not processed ***\n// %s\n' % (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 (!%s(result, "%s" %s))\n\t\treturn MAKE_PYCOM_GATEWAY_FAILURE_CODE("%s");\n' % (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")
|
317
venv/Lib/site-packages/win32com/makegw/makegwenum.py
Normal file
317
venv/Lib/site-packages/win32com/makegw/makegwenum.py
Normal file
|
@ -0,0 +1,317 @@
|
|||
"""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
|
||||
#
|
||||
#
|
||||
import string
|
||||
|
||||
def is_interface_enum(enumtype):
|
||||
return not (enumtype[0] in string.uppercase and enumtype[2] in string.uppercase)
|
||||
|
||||
|
||||
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)s, FALSE);" % locals()
|
||||
arraydeclare = "%(enum_interface)s **rgVar = new %(enum_interface)s *[celt];" % locals()
|
||||
else:
|
||||
# Enum of a simple structure
|
||||
converter = "PyObject *ob = PyCom_PyObjectFrom%(enumtype)s(&rgVar[i]);" % locals()
|
||||
arraydeclare = "%(enumtype)s *rgVar = new %(enumtype)s[celt];" % locals()
|
||||
|
||||
f.write(\
|
||||
'''
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Interface Implementation
|
||||
|
||||
PyIEnum%(enumtype)s::PyIEnum%(enumtype)s(IUnknown *pdisp):
|
||||
PyIUnknown(pdisp)
|
||||
{
|
||||
ob_type = &type;
|
||||
}
|
||||
|
||||
PyIEnum%(enumtype)s::~PyIEnum%(enumtype)s()
|
||||
{
|
||||
}
|
||||
|
||||
/* static */ IEnum%(enumtype)s *PyIEnum%(enumtype)s::GetI(PyObject *self)
|
||||
{
|
||||
return (IEnum%(enumtype)s *)PyIUnknown::GetI(self);
|
||||
}
|
||||
|
||||
// @pymethod object|PyIEnum%(enumtype)s|Next|Retrieves a specified number of items in the enumeration sequence.
|
||||
PyObject *PyIEnum%(enumtype)s::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)s *pIE%(enumtype)s = GetI(self);
|
||||
if ( pIE%(enumtype)s == NULL )
|
||||
return NULL;
|
||||
|
||||
%(arraydeclare)s
|
||||
if ( rgVar == NULL ) {
|
||||
PyErr_SetString(PyExc_MemoryError, "allocating result %(enumtype)ss");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int i;
|
||||
/* for ( i = celt; i--; )
|
||||
// *** possibly init each structure element???
|
||||
*/
|
||||
|
||||
ULONG celtFetched = 0;
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE%(enumtype)s->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)s, IID_IE%(enumtype)s);
|
||||
}
|
||||
|
||||
PyObject *result = PyTuple_New(celtFetched);
|
||||
if ( result != NULL )
|
||||
{
|
||||
for ( i = celtFetched; i--; )
|
||||
{
|
||||
%(converter)s
|
||||
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)s|Skip|Skips over the next specified elementes.
|
||||
PyObject *PyIEnum%(enumtype)s::Skip(PyObject *self, PyObject *args)
|
||||
{
|
||||
long celt;
|
||||
if ( !PyArg_ParseTuple(args, "l:Skip", &celt) )
|
||||
return NULL;
|
||||
|
||||
IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
|
||||
if ( pIE%(enumtype)s == NULL )
|
||||
return NULL;
|
||||
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE%(enumtype)s->Skip(celt);
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// @pymethod |PyIEnum%(enumtype)s|Reset|Resets the enumeration sequence to the beginning.
|
||||
PyObject *PyIEnum%(enumtype)s::Reset(PyObject *self, PyObject *args)
|
||||
{
|
||||
if ( !PyArg_ParseTuple(args, ":Reset") )
|
||||
return NULL;
|
||||
|
||||
IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
|
||||
if ( pIE%(enumtype)s == NULL )
|
||||
return NULL;
|
||||
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE%(enumtype)s->Reset();
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// @pymethod <o PyIEnum%(enumtype)s>|PyIEnum%(enumtype)s|Clone|Creates another enumerator that contains the same enumeration state as the current one
|
||||
PyObject *PyIEnum%(enumtype)s::Clone(PyObject *self, PyObject *args)
|
||||
{
|
||||
if ( !PyArg_ParseTuple(args, ":Clone") )
|
||||
return NULL;
|
||||
|
||||
IEnum%(enumtype)s *pIE%(enumtype)s = GetI(self);
|
||||
if ( pIE%(enumtype)s == NULL )
|
||||
return NULL;
|
||||
|
||||
IEnum%(enumtype)s *pClone;
|
||||
PY_INTERFACE_PRECALL;
|
||||
HRESULT hr = pIE%(enumtype)s->Clone(&pClone);
|
||||
PY_INTERFACE_POSTCALL;
|
||||
if ( FAILED(hr) )
|
||||
return PyCom_BuildPyException(hr, pIE%(enumtype)s, IID_IE%(enumtype)s);
|
||||
|
||||
return PyCom_PyObjectFromIUnknown(pClone, IID_IEnum%(enumtype)s, FALSE);
|
||||
}
|
||||
|
||||
// @object PyIEnum%(enumtype)s|A Python interface to IEnum%(enumtype)s
|
||||
static struct PyMethodDef PyIEnum%(enumtype)s_methods[] =
|
||||
{
|
||||
{ "Next", PyIEnum%(enumtype)s::Next, 1 }, // @pymeth Next|Retrieves a specified number of items in the enumeration sequence.
|
||||
{ "Skip", PyIEnum%(enumtype)s::Skip, 1 }, // @pymeth Skip|Skips over the next specified elementes.
|
||||
{ "Reset", PyIEnum%(enumtype)s::Reset, 1 }, // @pymeth Reset|Resets the enumeration sequence to the beginning.
|
||||
{ "Clone", PyIEnum%(enumtype)s::Clone, 1 }, // @pymeth Clone|Creates another enumerator that contains the same enumeration state as the current one.
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
PyComEnumTypeObject PyIEnum%(enumtype)s::type("PyIEnum%(enumtype)s",
|
||||
&PyIUnknown::type,
|
||||
sizeof(PyIEnum%(enumtype)s),
|
||||
PyIEnum%(enumtype)s_methods,
|
||||
GET_PYCOM_CTOR(PyIEnum%(enumtype)s));
|
||||
''' % 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)s, (void **)&rgVar[i], FALSE) )" % locals()
|
||||
argdeclare="%(enum_interface)s __RPC_FAR * __RPC_FAR *rgVar" % locals()
|
||||
else:
|
||||
argdeclare="%(enumtype)s __RPC_FAR *rgVar" % locals()
|
||||
converter="if ( !PyCom_PyObjectAs%(enumtype)s(ob, &rgVar[i]) )" % locals()
|
||||
f.write(
|
||||
'''
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Gateway Implementation
|
||||
|
||||
// Std delegation
|
||||
STDMETHODIMP_(ULONG) PyGEnum%(enumtype)s::AddRef(void) {return PyGatewayBase::AddRef();}
|
||||
STDMETHODIMP_(ULONG) PyGEnum%(enumtype)s::Release(void) {return PyGatewayBase::Release();}
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::QueryInterface(REFIID iid, void ** obj) {return PyGatewayBase::QueryInterface(iid, obj);}
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::GetTypeInfoCount(UINT FAR* pctInfo) {return PyGatewayBase::GetTypeInfoCount(pctInfo);}
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptInfo) {return PyGatewayBase::GetTypeInfo(itinfo, lcid, pptInfo);}
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::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)s::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)s::Next(
|
||||
/* [in] */ ULONG celt,
|
||||
/* [length_is][size_is][out] */ %(argdeclare)s,
|
||||
/* [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)s
|
||||
{
|
||||
Py_DECREF(result);
|
||||
return PyCom_SetCOMErrorFromPyException(IID_IEnum%(enumtype)s);
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(result);
|
||||
|
||||
return len < (int)celt ? S_FALSE : S_OK;
|
||||
|
||||
error:
|
||||
PyErr_Clear(); // just in case
|
||||
Py_DECREF(result);
|
||||
return PyCom_SetCOMErrorFromSimple(E_FAIL, IID_IEnum%(enumtype)s, "Next() did not return a sequence of objects");
|
||||
}
|
||||
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::Skip(
|
||||
/* [in] */ ULONG celt)
|
||||
{
|
||||
PY_GATEWAY_METHOD;
|
||||
return InvokeViaPolicy("Skip", NULL, "i", celt);
|
||||
}
|
||||
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::Reset(void)
|
||||
{
|
||||
PY_GATEWAY_METHOD;
|
||||
return InvokeViaPolicy("Reset");
|
||||
}
|
||||
|
||||
STDMETHODIMP PyGEnum%(enumtype)s::Clone(
|
||||
/* [out] */ IEnum%(enumtype)s __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)s);
|
||||
}
|
||||
|
||||
/*
|
||||
** 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)s);
|
||||
}
|
||||
|
||||
/*
|
||||
** Get the interface we want. note it is returned with a refcount.
|
||||
** This QI is actually going to instantiate a PyGEnum%(enumtype)s.
|
||||
*/
|
||||
hr = punk->QueryInterface(IID_IEnum%(enumtype)s, (LPVOID *)ppEnum);
|
||||
|
||||
/* done with the result; this DECREF is also for <punk> */
|
||||
Py_DECREF(result);
|
||||
|
||||
return PyCom_SetCOMErrorFromSimple(hr, IID_IEnum%(enumtype)s, "Python could not convert the result from Next() into the required COM interface");
|
||||
}
|
||||
''' % locals())
|
783
venv/Lib/site-packages/win32com/makegw/makegwparse.py
Normal file
783
venv/Lib/site-packages/win32com/makegw/makegwparse.py
Normal file
|
@ -0,0 +1,783 @@
|
|||
"""Utilities for makegw - Parse a header file to build an interface
|
||||
|
||||
This module contains the core code for parsing a header file describing a
|
||||
COM interface, and building it into an "Interface" structure.
|
||||
|
||||
Each Interface has methods, and each method has arguments.
|
||||
|
||||
Each argument knows how to use Py_BuildValue or Py_ParseTuple to
|
||||
exchange itself with Python.
|
||||
|
||||
See the @win32com.makegw@ module for information in building a COM
|
||||
interface
|
||||
"""
|
||||
import re
|
||||
import traceback
|
||||
|
||||
class error_not_found(Exception):
|
||||
def __init__(self, msg="The requested item could not be found"):
|
||||
super(error_not_found, self).__init__(msg)
|
||||
|
||||
class error_not_supported(Exception):
|
||||
def __init__(self, msg="The required functionality is not supported"):
|
||||
super(error_not_supported, self).__init__(msg)
|
||||
|
||||
VERBOSE=0
|
||||
DEBUG=0
|
||||
|
||||
## NOTE : For interfaces as params to work correctly, you must
|
||||
## make sure any PythonCOM extensions which expose the interface are loaded
|
||||
## before generating.
|
||||
|
||||
|
||||
class ArgFormatter:
|
||||
"""An instance for a specific type of argument. Knows how to convert itself"""
|
||||
def __init__(self, arg, builtinIndirection, declaredIndirection = 0):
|
||||
#print 'init:', arg.name, builtinIndirection, declaredIndirection, arg.indirectionLevel
|
||||
self.arg = arg
|
||||
self.builtinIndirection = builtinIndirection
|
||||
self.declaredIndirection = declaredIndirection
|
||||
self.gatewayMode = 0
|
||||
def _IndirectPrefix(self, indirectionFrom, indirectionTo):
|
||||
"""Given the indirection level I was declared at (0=Normal, 1=*, 2=**)
|
||||
return a string prefix so I can pass to a function with the
|
||||
required indirection (where the default is the indirection of the method's param.
|
||||
|
||||
eg, assuming my arg has indirection level of 2, if this function was passed 1
|
||||
it would return "&", so that a variable declared with indirection of 1
|
||||
can be prefixed with this to turn it into the indirection level required of 2
|
||||
"""
|
||||
dif = indirectionFrom - indirectionTo
|
||||
if dif==0:
|
||||
return ""
|
||||
elif dif==-1:
|
||||
return "&"
|
||||
elif dif==1:
|
||||
return "*"
|
||||
else:
|
||||
return "?? (%d)" % (dif,)
|
||||
raise error_not_supported("Can't indirect this far - please fix me :-)")
|
||||
def GetIndirectedArgName(self, indirectFrom, indirectionTo):
|
||||
#print 'get:',self.arg.name, indirectFrom,self._GetDeclaredIndirection() + self.builtinIndirection, indirectionTo, self.arg.indirectionLevel
|
||||
|
||||
if indirectFrom is None:
|
||||
### ACK! this does not account for [in][out] variables.
|
||||
### when this method is called, we need to know which
|
||||
indirectFrom = self._GetDeclaredIndirection() + self.builtinIndirection
|
||||
|
||||
return self._IndirectPrefix(indirectFrom, indirectionTo) + self.arg.name
|
||||
def GetBuildValueArg(self):
|
||||
"Get the argument to be passes to Py_BuildValue"
|
||||
return self.arg.name
|
||||
def GetParseTupleArg(self):
|
||||
"Get the argument to be passed to PyArg_ParseTuple"
|
||||
if self.gatewayMode:
|
||||
# use whatever they were declared with
|
||||
return self.GetIndirectedArgName(None, 1)
|
||||
# local declarations have just their builtin indirection
|
||||
return self.GetIndirectedArgName(self.builtinIndirection, 1)
|
||||
def GetInterfaceCppObjectInfo(self):
|
||||
"""Provide information about the C++ object used.
|
||||
|
||||
Simple variables (such as integers) can declare their type (eg an integer)
|
||||
and use it as the target of both PyArg_ParseTuple and the COM function itself.
|
||||
|
||||
More complex types require a PyObject * declared as the target of PyArg_ParseTuple,
|
||||
then some conversion routine to the C++ object which is actually passed to COM.
|
||||
|
||||
This method provides the name, and optionally the type of that C++ variable.
|
||||
If the type if provided, the caller will likely generate a variable declaration.
|
||||
The name must always be returned.
|
||||
|
||||
Result is a tuple of (variableName, [DeclareType|None|""])
|
||||
"""
|
||||
|
||||
# the first return element is the variable to be passed as
|
||||
# an argument to an interface method. the variable was
|
||||
# declared with only its builtin indirection level. when
|
||||
# we pass it, we'll need to pass in whatever amount of
|
||||
# indirection was applied (plus the builtin amount)
|
||||
# the second return element is the variable declaration; it
|
||||
# should simply be builtin indirection
|
||||
return self.GetIndirectedArgName(self.builtinIndirection, self.arg.indirectionLevel + self.builtinIndirection), \
|
||||
"%s %s" % (self.GetUnconstType(), self.arg.name)
|
||||
|
||||
def GetInterfaceArgCleanup(self):
|
||||
"Return cleanup code for C++ args passed to the interface method."
|
||||
if DEBUG:
|
||||
return "/* GetInterfaceArgCleanup output goes here: %s */\n" % self.arg.name
|
||||
else:
|
||||
return ""
|
||||
|
||||
def GetInterfaceArgCleanupGIL(self):
|
||||
"""Return cleanup code for C++ args passed to the interface
|
||||
method that must be executed with the GIL held"""
|
||||
if DEBUG:
|
||||
return "/* GetInterfaceArgCleanup (GIL held) output goes here: %s */\n" % self.arg.name
|
||||
else:
|
||||
return ""
|
||||
|
||||
def GetUnconstType(self):
|
||||
return self.arg.unc_type
|
||||
|
||||
def SetGatewayMode(self):
|
||||
self.gatewayMode = 1
|
||||
def _GetDeclaredIndirection(self):
|
||||
return self.arg.indirectionLevel
|
||||
print('declared:', self.arg.name, self.gatewayMode)
|
||||
if self.gatewayMode:
|
||||
return self.arg.indirectionLevel
|
||||
else:
|
||||
return self.declaredIndirection
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
"Declare the variable used as the PyArg_ParseTuple param for a gateway"
|
||||
# Only declare it??
|
||||
#if self.arg.indirectionLevel==0:
|
||||
# return "\t%s %s;\n" % (self.arg.type, self.arg.name)
|
||||
#else:
|
||||
if DEBUG:
|
||||
return "/* Declare ParseArgTupleInputConverter goes here: %s */\n" % self.arg.name
|
||||
else:
|
||||
return ""
|
||||
def GetParsePostCode(self):
|
||||
"Get a string of C++ code to be executed after (ie, to finalise) the PyArg_ParseTuple conversion"
|
||||
if DEBUG:
|
||||
return "/* GetParsePostCode code goes here: %s */\n" % self.arg.name
|
||||
else:
|
||||
return ""
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
"Get a string of C++ code to be executed before (ie, to initialise) the Py_BuildValue conversion for Interfaces"
|
||||
if DEBUG:
|
||||
return "/* GetBuildForInterfacePreCode goes here: %s */\n" % self.arg.name
|
||||
else:
|
||||
return ""
|
||||
def GetBuildForGatewayPreCode(self):
|
||||
"Get a string of C++ code to be executed before (ie, to initialise) the Py_BuildValue conversion for Gateways"
|
||||
s = self.GetBuildForInterfacePreCode() # Usually the same
|
||||
if DEBUG:
|
||||
if s[:4] == "/* G":
|
||||
s = "/* GetBuildForGatewayPreCode goes here: %s */\n" % self.arg.name
|
||||
return s
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
"Get a string of C++ code to be executed after (ie, to finalise) the Py_BuildValue conversion for Interfaces"
|
||||
if DEBUG:
|
||||
return "/* GetBuildForInterfacePostCode goes here: %s */\n" % self.arg.name
|
||||
return ""
|
||||
def GetBuildForGatewayPostCode(self):
|
||||
"Get a string of C++ code to be executed after (ie, to finalise) the Py_BuildValue conversion for Gateways"
|
||||
s = self.GetBuildForInterfacePostCode() # Usually the same
|
||||
if DEBUG:
|
||||
if s[:4] == "/* G":
|
||||
s = "/* GetBuildForGatewayPostCode goes here: %s */\n" % self.arg.name
|
||||
return s
|
||||
def GetAutoduckString(self):
|
||||
return '// @pyparm %s|%s||Description for %s' % (self._GetPythonTypeDesc(), self.arg.name, self.arg.name)
|
||||
def _GetPythonTypeDesc(self):
|
||||
"Returns a string with the description of the type. Used for doco purposes"
|
||||
return None
|
||||
def NeedUSES_CONVERSION(self):
|
||||
"Determines if this arg forces a USES_CONVERSION macro"
|
||||
return 0
|
||||
|
||||
# Special formatter for floats since they're smaller than Python floats.
|
||||
class ArgFormatterFloat(ArgFormatter):
|
||||
def GetFormatChar(self):
|
||||
return "f"
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
# Declare a double variable
|
||||
return "\tdouble dbl%s;\n" % self.arg.name
|
||||
def GetParseTupleArg(self):
|
||||
return "&dbl" + self.arg.name
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "float"
|
||||
def GetBuildValueArg(self):
|
||||
return "&dbl" + self.arg.name
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
return "\tdbl" + self.arg.name + " = " + self.arg.name + ";\n"
|
||||
def GetBuildForGatewayPreCode(self):
|
||||
return "\tdbl%s = " % self.arg.name + self._IndirectPrefix( \
|
||||
self._GetDeclaredIndirection(),
|
||||
0) + self.arg.name + ";\n"
|
||||
def GetParsePostCode(self):
|
||||
s = "\t"
|
||||
if self.gatewayMode:
|
||||
s = s + self._IndirectPrefix(
|
||||
self._GetDeclaredIndirection(),
|
||||
0)
|
||||
s = s + self.arg.name
|
||||
s = s + " = (float)dbl%s;\n" % self.arg.name
|
||||
return s
|
||||
|
||||
# Special formatter for Shorts because they're
|
||||
# a different size than Python ints!
|
||||
class ArgFormatterShort(ArgFormatter):
|
||||
def GetFormatChar(self):
|
||||
return "i"
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
# Declare a double variable
|
||||
return "\tINT i%s;\n" % self.arg.name
|
||||
def GetParseTupleArg(self):
|
||||
return "&i" + self.arg.name
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "int"
|
||||
def GetBuildValueArg(self):
|
||||
return "&i" + self.arg.name
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
return "\ti" + self.arg.name + " = " + self.arg.name + ";\n"
|
||||
def GetBuildForGatewayPreCode(self):
|
||||
return "\ti%s = " % self.arg.name + self._IndirectPrefix( \
|
||||
self._GetDeclaredIndirection(),
|
||||
0) + self.arg.name + ";\n"
|
||||
def GetParsePostCode(self):
|
||||
s = "\t"
|
||||
if self.gatewayMode:
|
||||
s = s + self._IndirectPrefix(
|
||||
self._GetDeclaredIndirection(),
|
||||
0)
|
||||
s = s + self.arg.name
|
||||
s = s + " = i%s;\n" % self.arg.name
|
||||
return s
|
||||
|
||||
# for types which are 64bits on AMD64 - eg, HWND
|
||||
class ArgFormatterLONG_PTR(ArgFormatter):
|
||||
def GetFormatChar(self):
|
||||
return "O"
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
# Declare a PyObject variable
|
||||
return "\tPyObject *ob%s;\n" % self.arg.name
|
||||
def GetParseTupleArg(self):
|
||||
return "&ob"+self.arg.name
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "int/long"
|
||||
def GetBuildValueArg(self):
|
||||
return "ob" + self.arg.name
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
# Declare a PyObject variable
|
||||
return "\tPyObject *ob%s;\n" % self.arg.name
|
||||
|
||||
def GetParsePostCode(self):
|
||||
return "\tif (bPythonIsHappy && !PyWinLong_AsULONG_PTR(ob%s, (ULONG_PTR *)%s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = PyWinObject_FromULONG_PTR(%s);\n" % \
|
||||
(self.arg.name, notdirected)
|
||||
def GetBuildForGatewayPostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
|
||||
class ArgFormatterPythonCOM(ArgFormatter):
|
||||
"""An arg formatter for types exposed in the PythonCOM module"""
|
||||
def GetFormatChar(self):
|
||||
return "O"
|
||||
#def GetInterfaceCppObjectInfo(self):
|
||||
# return ArgFormatter.GetInterfaceCppObjectInfo(self)[0], \
|
||||
# "%s %s%s" % (self.arg.unc_type, "*" * self._GetDeclaredIndirection(), self.arg.name)
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
# Declare a PyObject variable
|
||||
return "\tPyObject *ob%s;\n" % self.arg.name
|
||||
def GetParseTupleArg(self):
|
||||
return "&ob"+self.arg.name
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o Py%s>" % self.arg.type
|
||||
def GetBuildValueArg(self):
|
||||
return "ob" + self.arg.name
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
def DeclareParseArgTupleInputConverter(self):
|
||||
# Declare a PyObject variable
|
||||
return "\tPyObject *ob%s;\n" % self.arg.name
|
||||
|
||||
class ArgFormatterBSTR(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o unicode>"
|
||||
def GetParsePostCode(self):
|
||||
return "\tif (bPythonIsHappy && !PyWinObject_AsBstr(ob%s, %s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = MakeBstrToObj(%s);\n" % \
|
||||
(self.arg.name, notdirected)
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
return "\tSysFreeString(%s);\n" % (self.arg.name,) + \
|
||||
ArgFormatterPythonCOM.GetBuildForInterfacePostCode(self)
|
||||
def GetBuildForGatewayPostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
|
||||
class ArgFormatterOLECHAR(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o unicode>"
|
||||
def GetUnconstType(self):
|
||||
if self.arg.type[:3]=="LPC":
|
||||
return self.arg.type[:2] + self.arg.type[3:]
|
||||
else:
|
||||
return self.arg.unc_type
|
||||
def GetParsePostCode(self):
|
||||
return "\tif (bPythonIsHappy && !PyWinObject_AsBstr(ob%s, %s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
|
||||
def GetInterfaceArgCleanup(self):
|
||||
return "\tSysFreeString(%s);\n" % self.GetIndirectedArgName(None, 1)
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
# the variable was declared with just its builtin indirection
|
||||
notdirected = self.GetIndirectedArgName(self.builtinIndirection, 1)
|
||||
return "\tob%s = MakeOLECHARToObj(%s);\n" % \
|
||||
(self.arg.name, notdirected)
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
# memory returned into an OLECHAR should be freed
|
||||
return "\tCoTaskMemFree(%s);\n" % (self.arg.name,) + \
|
||||
ArgFormatterPythonCOM.GetBuildForInterfacePostCode(self)
|
||||
def GetBuildForGatewayPostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
|
||||
class ArgFormatterTCHAR(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "string/<o unicode>"
|
||||
def GetUnconstType(self):
|
||||
if self.arg.type[:3]=="LPC":
|
||||
return self.arg.type[:2] + self.arg.type[3:]
|
||||
else:
|
||||
return self.arg.unc_type
|
||||
def GetParsePostCode(self):
|
||||
return "\tif (bPythonIsHappy && !PyWinObject_AsTCHAR(ob%s, %s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 2))
|
||||
def GetInterfaceArgCleanup(self):
|
||||
return "\tPyWinObject_FreeTCHAR(%s);\n" % self.GetIndirectedArgName(None, 1)
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
# the variable was declared with just its builtin indirection
|
||||
notdirected = self.GetIndirectedArgName(self.builtinIndirection, 1)
|
||||
return "\tob%s = PyWinObject_FromTCHAR(%s);\n" % \
|
||||
(self.arg.name, notdirected)
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
return "// ??? - TCHAR post code\n"
|
||||
def GetBuildForGatewayPostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
|
||||
class ArgFormatterIID(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o PyIID>"
|
||||
def GetParsePostCode(self):
|
||||
return "\tif (!PyWinObject_AsIID(ob%s, &%s)) bPythonIsHappy = FALSE;\n" % (self.arg.name, self.arg.name)
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
# notdirected = self.GetIndirectedArgName(self.arg.indirectionLevel, 0)
|
||||
notdirected = self.GetIndirectedArgName(None, 0)
|
||||
return "\tob%s = PyWinObject_FromIID(%s);\n" % (self.arg.name, notdirected)
|
||||
def GetInterfaceCppObjectInfo(self):
|
||||
return self.arg.name, "IID %s" % (self.arg.name)
|
||||
|
||||
class ArgFormatterTime(ArgFormatterPythonCOM):
|
||||
def __init__(self, arg, builtinIndirection, declaredIndirection = 0):
|
||||
# we don't want to declare LPSYSTEMTIME / LPFILETIME objects
|
||||
if arg.indirectionLevel == 0 and arg.unc_type[:2] == "LP":
|
||||
arg.unc_type = arg.unc_type[2:]
|
||||
# reduce the builtin and increment the declaration
|
||||
arg.indirectionLevel = arg.indirectionLevel + 1
|
||||
builtinIndirection = 0
|
||||
ArgFormatterPythonCOM.__init__(self, arg, builtinIndirection, declaredIndirection)
|
||||
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o PyTime>"
|
||||
def GetParsePostCode(self):
|
||||
# variable was declared with only the builtinIndirection
|
||||
### NOTE: this is an [in] ... so use only builtin
|
||||
return '\tif (!PyTime_Check(ob%s)) {\n\t\tPyErr_SetString(PyExc_TypeError, "The argument must be a PyTime object");\n\t\tbPythonIsHappy = FALSE;\n\t}\n\tif (!((PyTime *)ob%s)->GetTime(%s)) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.arg.name, self.GetIndirectedArgName(self.builtinIndirection, 1))
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
### use just the builtinIndirection again...
|
||||
notdirected = self.GetIndirectedArgName(self.builtinIndirection,0)
|
||||
return "\tob%s = new PyTime(%s);\n" % (self.arg.name, notdirected)
|
||||
def GetBuildForInterfacePostCode(self):
|
||||
### hack to determine if we need to free stuff
|
||||
ret = ''
|
||||
if self.builtinIndirection + self.arg.indirectionLevel > 1:
|
||||
# memory returned into an OLECHAR should be freed
|
||||
ret = "\tCoTaskMemFree(%s);\n" % self.arg.name
|
||||
return ret + ArgFormatterPythonCOM.GetBuildForInterfacePostCode(self)
|
||||
|
||||
class ArgFormatterSTATSTG(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o STATSTG>"
|
||||
def GetParsePostCode(self):
|
||||
return '\tif (!PyCom_PyObjectAsSTATSTG(ob%s, %s, 0/*flags*/)) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = PyCom_PyObjectFromSTATSTG(%s);\n\t// STATSTG doco says our responsibility to free\n\tif ((%s).pwcsName) CoTaskMemFree((%s).pwcsName);\n" % (self.arg.name, self.GetIndirectedArgName(None, 1),notdirected,notdirected)
|
||||
|
||||
class ArgFormatterGeneric(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o %s>" % self.arg.type
|
||||
def GetParsePostCode(self):
|
||||
return '\tif (!PyObject_As%s(ob%s, &%s) bPythonIsHappy = FALSE;\n' % (self.arg.type, self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
def GetInterfaceArgCleanup(self):
|
||||
return '\tPyObject_Free%s(%s);\n' % (self.arg.type, self.arg.name)
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = PyObject_From%s(%s);\n" % (self.arg.name, self.arg.type, self.GetIndirectedArgName(None, 1))
|
||||
|
||||
class ArgFormatterIDLIST(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o PyIDL>"
|
||||
def GetParsePostCode(self):
|
||||
return '\tif (bPythonIsHappy && !PyObject_AsPIDL(ob%s, &%s)) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
def GetInterfaceArgCleanup(self):
|
||||
return '\tPyObject_FreePIDL(%s);\n' % (self.arg.name,)
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = PyObject_FromPIDL(%s);\n" % (self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
|
||||
class ArgFormatterHANDLE(ArgFormatterPythonCOM):
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o PyHANDLE>"
|
||||
def GetParsePostCode(self):
|
||||
return '\tif (!PyWinObject_AsHANDLE(ob%s, &%s, FALSE) bPythonIsHappy = FALSE;\n' % (self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = PyWinObject_FromHANDLE(%s);\n" % (self.arg.name, self.GetIndirectedArgName(None, 0))
|
||||
|
||||
class ArgFormatterLARGE_INTEGER(ArgFormatterPythonCOM):
|
||||
def GetKeyName(self):
|
||||
return "LARGE_INTEGER"
|
||||
def _GetPythonTypeDesc(self):
|
||||
return "<o %s>" % self.GetKeyName()
|
||||
def GetParsePostCode(self):
|
||||
return '\tif (!PyWinObject_As%s(ob%s, %s)) bPythonIsHappy = FALSE;\n' % (self.GetKeyName(), self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 0)
|
||||
return "\tob%s = PyWinObject_From%s(%s);\n" % (self.arg.name, self.GetKeyName(), notdirected)
|
||||
|
||||
class ArgFormatterULARGE_INTEGER(ArgFormatterLARGE_INTEGER):
|
||||
def GetKeyName(self):
|
||||
return "ULARGE_INTEGER"
|
||||
|
||||
class ArgFormatterInterface(ArgFormatterPythonCOM):
|
||||
def GetInterfaceCppObjectInfo(self):
|
||||
return self.GetIndirectedArgName(1, self.arg.indirectionLevel), \
|
||||
"%s * %s" % (self.GetUnconstType(), self.arg.name)
|
||||
|
||||
def GetParsePostCode(self):
|
||||
# This gets called for out params in gateway mode
|
||||
if self.gatewayMode:
|
||||
sArg = self.GetIndirectedArgName(None, 2)
|
||||
else:
|
||||
# vs. in params for interface mode.
|
||||
sArg = self.GetIndirectedArgName(1, 2)
|
||||
return "\tif (bPythonIsHappy && !PyCom_InterfaceFromPyInstanceOrObject(ob%s, IID_%s, (void **)%s, TRUE /* bNoneOK */))\n\t\t bPythonIsHappy = FALSE;\n" % (self.arg.name, self.arg.type, sArg)
|
||||
|
||||
def GetBuildForInterfacePreCode(self):
|
||||
return "\tob%s = PyCom_PyObjectFromIUnknown(%s, IID_%s, FALSE);\n" % (self.arg.name, self.arg.name, self.arg.type)
|
||||
|
||||
def GetBuildForGatewayPreCode(self):
|
||||
sPrefix = self._IndirectPrefix(self._GetDeclaredIndirection(), 1)
|
||||
return "\tob%s = PyCom_PyObjectFromIUnknown(%s%s, IID_%s, TRUE);\n" % (self.arg.name, sPrefix, self.arg.name, self.arg.type)
|
||||
|
||||
def GetInterfaceArgCleanup(self):
|
||||
return "\tif (%s) %s->Release();\n" % (self.arg.name, self.arg.name)
|
||||
|
||||
class ArgFormatterVARIANT(ArgFormatterPythonCOM):
|
||||
def GetParsePostCode(self):
|
||||
return "\tif ( !PyCom_VariantFromPyObject(ob%s, %s) )\n\t\tbPythonIsHappy = FALSE;\n" % (self.arg.name, self.GetIndirectedArgName(None, 1))
|
||||
|
||||
def GetBuildForGatewayPreCode(self):
|
||||
notdirected = self.GetIndirectedArgName(None, 1)
|
||||
return "\tob%s = PyCom_PyObjectFromVariant(%s);\n" % (self.arg.name, notdirected)
|
||||
def GetBuildForGatewayPostCode(self):
|
||||
return "\tPy_XDECREF(ob%s);\n" % self.arg.name
|
||||
|
||||
# Key : , Python Type Description, ParseTuple format char
|
||||
ConvertSimpleTypes = {"BOOL":("BOOL", "int", "i"),
|
||||
"UINT":("UINT", "int", "i"),
|
||||
"BYTE": ("BYTE", "int", "i"),
|
||||
"INT": ("INT", "int", "i"),
|
||||
"DWORD": ("DWORD", "int", "l"),
|
||||
"HRESULT":("HRESULT", "int", "l"),
|
||||
"ULONG": ("ULONG", "int", "l"),
|
||||
"LONG": ("LONG", "int", "l"),
|
||||
"int": ("int", "int", "i"),
|
||||
"long": ("long", "int", "l"),
|
||||
"DISPID": ("DISPID", "long", "l"),
|
||||
"APPBREAKFLAGS": ("int", "int", "i"),
|
||||
"BREAKRESUMEACTION": ("int", "int", "i"),
|
||||
"ERRORRESUMEACTION": ("int", "int", "i"),
|
||||
"BREAKREASON": ("int", "int", "i"),
|
||||
"BREAKPOINT_STATE": ("int", "int", "i"),
|
||||
"BREAKRESUME_ACTION": ("int", "int", "i"),
|
||||
"SOURCE_TEXT_ATTR": ("int", "int", "i"),
|
||||
"TEXT_DOC_ATTR": ("int", "int", "i"),
|
||||
"QUERYOPTION": ("int", "int", "i"),
|
||||
"PARSEACTION": ("int", "int", "i"),
|
||||
}
|
||||
|
||||
class ArgFormatterSimple(ArgFormatter):
|
||||
"""An arg formatter for simple integer etc types"""
|
||||
def GetFormatChar(self):
|
||||
return ConvertSimpleTypes[self.arg.type][2]
|
||||
def _GetPythonTypeDesc(self):
|
||||
return ConvertSimpleTypes[self.arg.type][1]
|
||||
|
||||
AllConverters = {"const OLECHAR": (ArgFormatterOLECHAR, 0, 1),
|
||||
"WCHAR": (ArgFormatterOLECHAR, 0, 1),
|
||||
"OLECHAR": (ArgFormatterOLECHAR, 0, 1),
|
||||
"LPCOLESTR": (ArgFormatterOLECHAR, 1, 1),
|
||||
"LPOLESTR": (ArgFormatterOLECHAR, 1, 1),
|
||||
"LPCWSTR": (ArgFormatterOLECHAR, 1, 1),
|
||||
"LPWSTR": (ArgFormatterOLECHAR, 1, 1),
|
||||
"LPCSTR": (ArgFormatterOLECHAR, 1, 1),
|
||||
"LPTSTR": (ArgFormatterTCHAR, 1, 1),
|
||||
"LPCTSTR": (ArgFormatterTCHAR, 1, 1),
|
||||
"HANDLE": (ArgFormatterHANDLE, 0),
|
||||
"BSTR": (ArgFormatterBSTR, 1, 0),
|
||||
"const IID": (ArgFormatterIID, 0),
|
||||
"CLSID": (ArgFormatterIID, 0),
|
||||
"IID": (ArgFormatterIID, 0),
|
||||
"GUID": (ArgFormatterIID, 0),
|
||||
"const GUID": (ArgFormatterIID, 0),
|
||||
"const IID": (ArgFormatterIID, 0),
|
||||
"REFCLSID": (ArgFormatterIID, 0),
|
||||
"REFIID": (ArgFormatterIID, 0),
|
||||
"REFGUID": (ArgFormatterIID, 0),
|
||||
"const FILETIME": (ArgFormatterTime, 0),
|
||||
"const SYSTEMTIME":(ArgFormatterTime, 0),
|
||||
"const LPSYSTEMTIME":(ArgFormatterTime, 1, 1),
|
||||
"LPSYSTEMTIME": (ArgFormatterTime, 1, 1),
|
||||
"FILETIME": (ArgFormatterTime, 0),
|
||||
"SYSTEMTIME": (ArgFormatterTime, 0),
|
||||
"STATSTG": (ArgFormatterSTATSTG, 0),
|
||||
"LARGE_INTEGER": (ArgFormatterLARGE_INTEGER, 0),
|
||||
"ULARGE_INTEGER": (ArgFormatterULARGE_INTEGER, 0),
|
||||
"VARIANT": (ArgFormatterVARIANT, 0),
|
||||
"float": (ArgFormatterFloat, 0),
|
||||
"single": (ArgFormatterFloat, 0),
|
||||
"short": (ArgFormatterShort, 0),
|
||||
"WORD": (ArgFormatterShort, 0),
|
||||
"VARIANT_BOOL": (ArgFormatterShort, 0),
|
||||
"HWND": (ArgFormatterLONG_PTR, 1),
|
||||
"HMENU": (ArgFormatterLONG_PTR, 1),
|
||||
"HOLEMENU": (ArgFormatterLONG_PTR, 1),
|
||||
"HICON": (ArgFormatterLONG_PTR, 1),
|
||||
"HDC": (ArgFormatterLONG_PTR, 1),
|
||||
"LPARAM": (ArgFormatterLONG_PTR, 1),
|
||||
"WPARAM": (ArgFormatterLONG_PTR, 1),
|
||||
"LRESULT": (ArgFormatterLONG_PTR, 1),
|
||||
"UINT": (ArgFormatterShort, 0),
|
||||
"SVSIF": (ArgFormatterShort, 0),
|
||||
"Control": (ArgFormatterInterface, 0, 1),
|
||||
"DataObject": (ArgFormatterInterface, 0, 1),
|
||||
"_PropertyBag": (ArgFormatterInterface, 0, 1),
|
||||
"AsyncProp": (ArgFormatterInterface, 0, 1),
|
||||
"DataSource": (ArgFormatterInterface, 0, 1),
|
||||
"DataFormat": (ArgFormatterInterface, 0, 1),
|
||||
"void **": (ArgFormatterInterface, 2, 2),
|
||||
"ITEMIDLIST": (ArgFormatterIDLIST, 0, 0),
|
||||
"LPITEMIDLIST": (ArgFormatterIDLIST, 0, 1),
|
||||
"LPCITEMIDLIST": (ArgFormatterIDLIST, 0, 1),
|
||||
"const ITEMIDLIST": (ArgFormatterIDLIST, 0, 1),
|
||||
}
|
||||
|
||||
# Auto-add all the simple types
|
||||
for key in ConvertSimpleTypes.keys():
|
||||
AllConverters[key] = ArgFormatterSimple, 0
|
||||
|
||||
def make_arg_converter(arg):
|
||||
try:
|
||||
clz = AllConverters[arg.type][0]
|
||||
bin = AllConverters[arg.type][1]
|
||||
decl = 0
|
||||
if len(AllConverters[arg.type])>2:
|
||||
decl = AllConverters[arg.type][2]
|
||||
return clz(arg,bin, decl)
|
||||
except KeyError:
|
||||
if arg.type[0]=="I":
|
||||
return ArgFormatterInterface(arg, 0, 1)
|
||||
|
||||
raise error_not_supported("The type '%s' (%s) is unknown." % (arg.type, arg.name))
|
||||
|
||||
|
||||
#############################################################
|
||||
#
|
||||
# The instances that represent the args, methods and interface
|
||||
class Argument:
|
||||
"""A representation of an argument to a COM method
|
||||
|
||||
This class contains information about a specific argument to a method.
|
||||
In addition, methods exist so that an argument knows how to convert itself
|
||||
to/from Python arguments.
|
||||
"""
|
||||
# in,out type name [ ]
|
||||
# -------------- -------- ------------ ------
|
||||
regex = re.compile(r'/\* \[([^\]]*.*?)] \*/[ \t](.*[* ]+)(\w+)(\[ *])?[\),]')
|
||||
def __init__(self, good_interface_names):
|
||||
self.good_interface_names = good_interface_names
|
||||
self.inout = self.name = self.type = None
|
||||
self.const = 0
|
||||
self.arrayDecl = 0
|
||||
def BuildFromFile(self, file):
|
||||
"""Parse and build my data from a file
|
||||
|
||||
Reads the next line in the file, and matches it as an argument
|
||||
description. If not a valid argument line, an error_not_found exception
|
||||
is raised.
|
||||
"""
|
||||
line = file.readline()
|
||||
mo = self.regex.search(line)
|
||||
if not mo:
|
||||
raise error_not_found
|
||||
self.name = mo.group(3)
|
||||
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 = typ.replace("__RPC_FAR", "")
|
||||
while 1:
|
||||
try:
|
||||
pos = typ.rindex("*")
|
||||
self.indirectionLevel = self.indirectionLevel + 1
|
||||
typ = typ[:pos].strip()
|
||||
except ValueError:
|
||||
break
|
||||
self.type = typ
|
||||
if self.type[:6]=="const ":
|
||||
self.unc_type = self.type[6:]
|
||||
else:
|
||||
self.unc_type = self.type
|
||||
|
||||
if VERBOSE:
|
||||
print(" Arg %s of type %s%s (%s)" % (self.name, self.type, "*" * self.indirectionLevel, self.inout))
|
||||
|
||||
def HasAttribute(self, typ):
|
||||
"""Determines if the argument has the specific attribute.
|
||||
|
||||
Argument attributes are specified in the header file, such as
|
||||
"[in][out][retval]" etc. You can pass a specific string (eg "out")
|
||||
to find if this attribute was specified for the argument
|
||||
"""
|
||||
return typ in self.inout
|
||||
|
||||
def GetRawDeclaration(self):
|
||||
ret = "%s %s" % (self.raw_type, self.name)
|
||||
if self.arrayDecl:
|
||||
ret = ret + "[]"
|
||||
return ret
|
||||
|
||||
class Method:
|
||||
"""A representation of a C++ method on a COM interface
|
||||
|
||||
This class contains information about a specific method, as well as
|
||||
a list of all @Argument@s
|
||||
"""
|
||||
# options ret type callconv name
|
||||
# ----------------- -------- -------- --------
|
||||
regex = re.compile(r'virtual (/\*.*?\*/ )?(.*?) (.*?) (.*?)\(\w?')
|
||||
def __init__(self, good_interface_names):
|
||||
self.good_interface_names = good_interface_names
|
||||
self.name = self.result = self.callconv = None
|
||||
self.args = []
|
||||
def BuildFromFile(self, file):
|
||||
"""Parse and build my data from a file
|
||||
|
||||
Reads the next line in the file, and matches it as a method
|
||||
description. If not a valid method line, an error_not_found exception
|
||||
is raised.
|
||||
"""
|
||||
line = file.readline()
|
||||
mo = self.regex.search(line)
|
||||
if not mo:
|
||||
raise error_not_found
|
||||
self.name = mo.group(4)
|
||||
self.result = mo.group(2)
|
||||
if self.result != "HRESULT":
|
||||
if self.result=="DWORD": # DWORD is for old old stuff?
|
||||
print("Warning: Old style interface detected - compilation errors likely!")
|
||||
else:
|
||||
print("Method %s - Only HRESULT return types are supported." % self.name)
|
||||
# raise error_not_supported, if VERBOSE:
|
||||
print(" Method %s %s(" % (self.result, self.name))
|
||||
while 1:
|
||||
arg = Argument(self.good_interface_names)
|
||||
try:
|
||||
arg.BuildFromFile(file)
|
||||
self.args.append(arg)
|
||||
except error_not_found:
|
||||
break
|
||||
|
||||
class Interface:
|
||||
"""A representation of a C++ COM Interface
|
||||
|
||||
This class contains information about a specific interface, as well as
|
||||
a list of all @Method@s
|
||||
"""
|
||||
# name base
|
||||
# -------- --------
|
||||
regex = re.compile("(interface|) ([^ ]*) : public (.*)$")
|
||||
def __init__(self, mo):
|
||||
self.methods = []
|
||||
self.name = mo.group(2)
|
||||
self.base = mo.group(3)
|
||||
if VERBOSE:
|
||||
print("Interface %s : public %s" % (self.name, self.base))
|
||||
|
||||
def BuildMethods(self, file):
|
||||
"""Build all sub-methods for this interface"""
|
||||
# skip the next 2 lines.
|
||||
file.readline();file.readline();
|
||||
while 1:
|
||||
try:
|
||||
method = Method([self.name])
|
||||
method.BuildFromFile(file)
|
||||
self.methods.append(method)
|
||||
except error_not_found:
|
||||
break
|
||||
|
||||
def find_interface(interfaceName, file):
|
||||
"""Find and return an interface in a file
|
||||
|
||||
Given an interface name and file, search for the specified interface.
|
||||
|
||||
Upon return, the interface itself has been built,
|
||||
but not the methods.
|
||||
"""
|
||||
interface = None
|
||||
line = file.readline()
|
||||
while line:
|
||||
mo = Interface.regex.search(line)
|
||||
if mo:
|
||||
name = mo.group(2)
|
||||
print(name)
|
||||
AllConverters[name] = (ArgFormatterInterface, 0, 1)
|
||||
if name==interfaceName:
|
||||
interface = Interface(mo)
|
||||
interface.BuildMethods(file)
|
||||
line = file.readline()
|
||||
if interface:
|
||||
return interface
|
||||
raise error_not_found
|
||||
|
||||
|
||||
def parse_interface_info(interfaceName, file):
|
||||
"""Find, parse and return an interface in a file
|
||||
|
||||
Given an interface name and file, search for the specified interface.
|
||||
|
||||
Upon return, the interface itself is fully built,
|
||||
"""
|
||||
try:
|
||||
return find_interface(interfaceName, file)
|
||||
except re.error:
|
||||
traceback.print_exc()
|
||||
print("The interface could not be built, as the regular expression failed!")
|
||||
def test():
|
||||
f=open("d:\\msdev\\include\\objidl.h")
|
||||
try:
|
||||
parse_interface_info("IPersistStream", f)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def test_regex(r,text):
|
||||
res=r.search(text,0)
|
||||
if res==-1:
|
||||
print("** Not found")
|
||||
else:
|
||||
print("%d\n%s\n%s\n%s\n%s" % (res, r.group(1), r.group(2), r.group(3), r.group(4)))
|
Loading…
Add table
Add a link
Reference in a new issue