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. if buffer 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

Popular posts from this blog

compiler errors - Unable to compile a4tech-bloody-linux-driver on Linux Mint 18, nor Ubuntu 16.04 -

c# - AutoMapper - What's difference between Condition and PreCondition -