python - How to introspect win32com wrapper? -
i have device, records spectroscopic data , controlled 3rd-party application. automization purposes, want use com interface of application retrieve data in python. since there no proper documentation using api python, collected following code different web sources, obtains first frame:
comtypes.client.getmodule(('{1a762221-d8ba-11cf-afc2-508201c10000}', 3, 11)) import comtypes.gen.winx32lib winspeclib win32com.client.pythoncom.coinitialize() doc = win32com.client.dispatch("winx32.docfile") buffer = ctypes.c_float() frame = 1 spectrum = doc.getframe(frame, buffer)
however, call getframe
inconsistent definition in visual basic, provided manufacturer:
sub getframe(frame integer, buffer variant)
getframe
copies data document visual basic array. ifbuffer
empty variant,getframe
creates array of proper size , data type , sets buffer point before copying data.
this means in visual basic variable buffer
filled data while function getframe
has no return value, whereas in python buffer
remains unchanged function getframe
return actual data.
i wouldn't care such subtleties, if hadn't observed random crashes of program throwing memoryerror
, indicating memory leak @ point of code. suspicion each call getframe
memory allocated buffer never released, because win32com
somehow messed api wrapping.
that reasoning leads me actual question: how can introspect wrapper , understand does? far, not find hints code generated win32com
stored in file, maybe have not been looking @ right places.
in ipython tried information using doc.getframe??
, did not return implementation:
signature: doc.getframe(frame=<pyolemissing object @ 0x06f20bc8>, framevariant=<pyolemissing object @ 0x06f20bc8>) docstring: <no docstring> file: c:\programming\python\src\<comobject winx32.docfile> type: method
what else can try more information api wrapper?
trying around more, able find solution problem. first important realization finding calling ensuredispatch
instead of dispatch
gives me access wrapper generated win32com
.
>>> import win32com.client >>> doc = win32com.client.gencache.ensuredispatch ("winx32.docfile") >>> print(doc.getframe.__module__) 'win32com.gen_py.1a762221-d8ba-11cf-afc2-508201c10000x0x3x12.idocfile4'
in case corresponding file located in following folder:
c:\winpython\winpython-32bit-3.5.2.2\python-3.5.2\lib\site-packages\win32com\gen_py\1a762221-d8ba-11cf-afc2-508201c10000x0x3x12
the implementation of getframe
looks follows.
def getframe(self, frame=defaultnamednotoptarg, framevariant=defaultnamednotoptarg): 'get frame data' return self._applytypes_(10, 1, (24, 0), ((2, 1), (16396, 3)), 'getframe', none, frame, framevariant)
so magic in method _applytypes_
. method defined in win32com\client\__init__
.
def _applytypes_(self, dispid, wflags, rettype, argtypes, user, resultclsid, *args): return self._get_good_object_( self._oleobj_.invoketypes(dispid, 0, wflags, rettype, argtypes, *args), user, resultclsid)
we can see passed invoketypes
. according this message on python-win32 mailing list, invoketypes
similar invoke
, in turn re-implementation of idispatch::invoke
. source code of c++ implementation integrated in python can found here.
going through c++ implementation explains, bothered me in original question: python version of invoke
explicitly turns byref arguments return values. hence, @ least, there should no memory leak, suspected in beginning.
now can learn argument types? necessary information stored in tuple ((2, 1), (16396, 3))
. have 2 arguments, of first input argument (indicated 1
), while second input , output argument (indicated 3 = 1 | 2
). according this blog entry, respective first numbers tell kind of variant
datatype expected.
we can in this list, numbers mean. first argument signed int16
, makes sense, since specifies frame number. second number has following meaning.
16396 = 0x400c = vt_variant | vt_byref
the documentation tells us, vt_variant
means.
either specified type, or type of element or contained field must variant
not super instructive, still. seems choice pass ctypes.c_float
not choice. instead, passing variant, should, inspired this discussion.
var = win32com.client.variant(pythoncom.vt_variant | pythoncom.vt_null | pythoncom.vt_byref, none) spectrum = doc.getframe(frame, var)
since making change, have no longer observed crashes of code part, original question solved me.
Comments
Post a Comment