Discussion:
[python-win32] Python crash after win32com.client.CastTo?
Nathan Edwards
2005-03-21 14:46:26 UTC
Permalink
I'm going out of my mind here, trying to figure out if
a) I'm screwing up,
b) Python's COM extensions are screwing up, or
c) the Type Library I'm using is screwing up.

I have a small amount of experience with Visual Basic, but no experience
of the intricacies of COM interfaces. However, I am "merely" attempting
to port VB code that is known to work to a less restricted context (python).

The relevant code snippet looks like this:

Dim theFMANSpecData As New FMANSpecData
Dim theWF As FMANWiffFile
Dim theWF2 As IFMANWiffFile2

theFMANSpecData.wiffFilename = wiffFilename
Set theWF = theFMANSpecData.GetWiffFileObject
Set theWF2 = theWF

....

Call theWF2.GetScanDescription2(1, 0, 382, 1, 0, ScanDesc, fixedMass)

I've used makepy to ensure static binding, and translated to this
snippet as follows:

from win32com.client import Dispatch, CastTo
theFMANSpecData = Dispatch('Analyst.FMANSpecData')
theFMANSpecData.WiffFileName = wiffFilename
theWF = theFMANSpecData.GetWiffFileObject()
theWF2 = CastTo(theWF,'IFMANWiffFile2')

...

ScanDesc, fixedMass = theWF2.GetScanDescription2(1,0,382,1,0)

I've used many of the other elements of the Analyst application's
typelibs - they have all worked fine. This is the only case where a
non-default interface to a class is required.

When the python interpreter hits the call to GetScanDescription2, it
exits immediately, no exception, no error message, no nothing. Exit
status 5 (cygwin shell), %errorlevel% -1073741819 from cmd.exe prompt.

Python 2.4, pywin32-203 for Python 2.4.

I'm not even sure how to proceed to debug the problem.

The type library is propriatary (provided by an instrument vendor).
While it is possible the fault lies in that code, the library is used
(and run by me on the same computer) by the VB code snippet above.

python exits abruptly with no error message whether or not I use the
python binary or the pythonwin binary.

By inserting print statements into win32com/client/__init__.py, I've
established that the crash is occuring in the call to
self._oldobj_.InvokeTypes(...) in DispatchBaseClass._ApplyTypes_.

Having established this, I'm pretty confident of b) above.

The arguements to InvokeTypes are:

dispid = 1610678272
wFlags = 1
retType = (24, 0)
argTypes = ((3, 1), (3, 1), (3, 1), (3, 1), (3, 1), (16392, 2), (16389, 2))
args = (1, 0, 382, 1, 0, <PyOleMissing object at 0x009AF640>,
<PyOleMissing object at 0x009AF640>)

If this is a bug in pywin, is this enough information to fix it? If not,
how can I generate more helpful information?

Thanks!

nathan

nathan
--
Nathan Edwards, Ph.D.
Center for Bioinformatics and Computational Biology
3119 Agriculture/Life Sciences Surge Building #296
University of Maryland, College Park, MD 20742-3360
Phone: +1 301-405-9901
Email: ***@umiacs.umd.edu
WWWeb: http://www.umiacs.umd.edu/~nedwards
Mark Hammond
2005-03-21 22:15:37 UTC
Permalink
This post might be inappropriate. Click to display it.
Nathan Edwards
2005-03-22 14:10:00 UTC
Permalink
Post by Mark Hammond
Unfortunately, _InvokeTypes_ is the main "entry point" for *all* COM calls
with type information. As part of this call, Python packs all Python args
into VARIANTs, then makes the actual call to the COM object.
Hmmm. I was afraid of that.
Post by Mark Hammond
* pythoncom has a bug in InvokeTypes, probably in arg packing or unpacking.
Possible, but unlikely, since the args are ints with two pass by
reference parameters (string and float). Nothing hairy there, I exepct
that the argument unpacking and packing has proven itself over time.
Post by Mark Hammond
* The COM object has a bug once control has been passed to that.
I wouldn't be surprised, but given that very similar code works in VB,
I'm guessing the issue lies somewhere at the interface.
Post by Mark Hammond
If pythoncom does have such a bug, it is subtle - all other COM objects
generally work fine. Also, the symptoms don't really match what Python
would do - the only thing I can see that would cause Python to "abort" like
that is a call to Py_FatalError - that does indeed call the C 'abort'
function, but will always cause some short error text to be printed before
termination.
I agree.
Post by Mark Hammond
I'm afraid that my guess is that it is the remote object. If it happens
only after a CastTo, I suspect that something is going wrong there. Even
though we "CastTo" an interface (IFMANWiffFile2 in this example), we are
*still* using IDispatch on the object. If the remote object expected a
"real" interface rather than an IDispatch based one, or the CastTo source
object is incorrect, I could see how this could happen.
Given my inexperience with COM etc. I guess I don't really understand
the difference between a "real" interface vs a IDispatch one. The VB
code declared the variables:

Dim theFMANSpecData As New FMANSpecData
Dim theWF As FMANWiffFile
Dim theWF2 As IFMANWiffFile2

Here, theWF is declared as a FMANWiffFile (CoClass), while theWF2 is
declared as IFMANWiffFile2 (Non-default Dispatch for FMANWiffFile).
Using Dispatch(...), when I ask for an FMANWiffFile, I get a
IFMANWiffFile (default Dispatch for FMANWiffFile). I can't do an
explicit Dispatch('Analyst.IFMANWiffFile2') (not a valid class string).

Later, again in VB, we have

theWF = theFMANSpecData.GetWiffFileObject()
theWF2 = theWF

Is the CastTo "equivalent" to this assignment?

Thanks,

nathan
--
Nathan Edwards, Ph.D.
Center for Bioinformatics and Computational Biology
3119 Agriculture/Life Sciences Surge Building #296
University of Maryland, College Park, MD 20742-3360
Phone: +1 301-405-9901
Email: ***@umiacs.umd.edu
WWWeb: http://www.umiacs.umd.edu/~nedwards
Tim Roberts
2005-03-22 19:01:57 UTC
Permalink
On Mon, 21 Mar 2005 09:46:26 -0500, Nathan Edwards
Post by Nathan Edwards
I'm going out of my mind here, trying to figure out if
a) I'm screwing up,
b) Python's COM extensions are screwing up, or
c) the Type Library I'm using is screwing up.
... Call theWF2.GetScanDescription2(1, 0, 382, 1, 0, ScanDesc, fixedMass)
I've used makepy to ensure static binding, and translated to this
from win32com.client import Dispatch, CastTo
theFMANSpecData = Dispatch('Analyst.FMANSpecData')
theFMANSpecData.WiffFileName = wiffFilename
theWF = theFMANSpecData.GetWiffFileObject()
theWF2 = CastTo(theWF,'IFMANWiffFile2')
...
ScanDesc, fixedMass = theWF2.GetScanDescription2(1,0,382,1,0)
I've used many of the other elements of the Analyst application's
typelibs - they have all worked fine. This is the only case where a
non-default interface to a class is required.
When the python interpreter hits the call to GetScanDescription2, it
exits immediately, no exception, no error message, no nothing. Exit
status 5 (cygwin shell), %errorlevel% -1073741819 from cmd.exe prompt.
For what it's worth, -1073741819 is hex C0000005, which is
STATUS_ACCESS_VIOLATION: a general protection fault. That's usually a
wild address or a null pointer dereference. Is it possible that one of
those last two parameters is actually (in,out) and not just (out)?
--
- Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Nathan Edwards
2005-03-23 21:50:24 UTC
Permalink
Post by Tim Roberts
For what it's worth, -1073741819 is hex C0000005, which is
STATUS_ACCESS_VIOLATION: a general protection fault. That's usually a
wild address or a null pointer dereference. Is it possible that one of
those last two parameters is actually (in,out) and not just (out)?
The generated function declaration indicates they are both out
(PyOleMissing object type), but who knows what the library internally
expects...
Post by Tim Roberts
help(theWF2.GetScanDescription2)
Help on method GetScanDescription2 in module
win32com.gen_py.5F259202-611C-11D1-A9C6-0060977F5C78x0x1x0:

GetScanDescription2(self, sample=<PyOleEmpty object>, period=<PyOleEmpty
object>, experiment=<PyOleEmpty object>, cycle=<PyOleEmpty object>,
forChromatogram=<PyOleEmpty object>, scanDescription=<PyOleMissing
object>, fixedMass=<PyOleMissing object>) method of
win32com.gen_py.5F259202-611C-11D1-A9C6-0060977F5C78x0x1x0.IFMANWiffFile2
instance
method GetScanDescription2

Its only weak evidence, but when I feed in invalid input parameters,
which for other functions in this library generates exceptions, the
crash happens anyway (implies that even the parameter checking doesn't
get done, and since this usually is done first, before any other stuff
happens, it suggests we don't even make it into the library function
proper.)

Cheers!

nathan
--
Nathan Edwards, Ph.D.
Center for Bioinformatics and Computational Biology
3119 Agriculture/Life Sciences Surge Building #296
University of Maryland, College Park, MD 20742-3360
Phone: +1 301-405-9901
Email: ***@umiacs.umd.edu
WWWeb: http://www.umiacs.umd.edu/~nedwards
Mark Hammond
2005-03-24 02:27:15 UTC
Permalink
Post by Tim Roberts
Post by Tim Roberts
For what it's worth, -1073741819 is hex C0000005, which is
STATUS_ACCESS_VIOLATION: a general protection fault.
That's usually a
Post by Tim Roberts
wild address or a null pointer dereference. Is it possible
that one of
Post by Tim Roberts
those last two parameters is actually (in,out) and not just (out)?
The generated function declaration indicates they are both out
(PyOleMissing object type), but who knows what the library internally
expects...
Post by Tim Roberts
help(theWF2.GetScanDescription2)
Help on method GetScanDescription2 in module
GetScanDescription2(self, sample=<PyOleEmpty object>,
period=<PyOleEmpty
object>, experiment=<PyOleEmpty object>, cycle=<PyOleEmpty object>,
forChromatogram=<PyOleEmpty object>, scanDescription=<PyOleMissing
object>, fixedMass=<PyOleMissing object>) method of
win32com.gen_py.5F259202-611C-11D1-A9C6-0060977F5C78x0x1x0.IFM
ANWiffFile2
instance
method GetScanDescription2
Try passing explicit args for every arg, or substituting pythoncom.Missing
instead of pythoncom.Empty.

Mark
Nathan Edwards
2005-03-24 02:54:46 UTC
Permalink
Post by Mark Hammond
Try passing explicit args for every arg, or substituting pythoncom.Missing
instead of pythoncom.Empty.
Already tried the first (same result-immediate crash). Don't understand
the second...

I've tried explicit "correct value and type" and "incorrect value but
correct type" args for every arg, immediate crash in each case.

I've come across another strange behavior that I don't understand...this
type library has another class that is the "blessed" way to get an
object of the type I'm having trouble with. However, I can't get the
interface object to instantiate:

# This CoClass is known by the name 'Analyst.FMANWiffFileControl.1'
class FMANWiffFileControl(CoClassBaseClass): # A CoClass
# FMANWiffFileControl Class
CLSID = IID('{A1A48EC4-98C6-11D1-A9F6-0060977F5C78}')
coclass_sources = [
]
coclass_interfaces = [
IFMANWiffFileControl,
]
default_interface = IFMANWiffFileControl

class IFMANWiffFileControl(DispatchBaseClass):
"""IFMANWiffFileControl Interface"""
CLSID = IID('{A1A48EC3-98C6-11D1-A9F6-0060977F5C78}')
coclass_clsid = IID('{A1A48EC4-98C6-11D1-A9F6-0060977F5C78}')

# Result is of type IFMANWiffFile
def GetWiffFileObject(self, WiffFileName=defaultNamedNotOptArg,
sample=defaultNamedNotOptArg):
"""method GetWiffFileObject"""
ret = self._oleobj_.InvokeTypes(1, LCID, 1, (9, 0), ((8, 1), (3,
1)),WiffFileName, sample)
if ret is not None:
ret = Dispatch(ret, 'GetWiffFileObject',
'{26E42183-9803-11D1-A9F6-0060977F5C78}', UnicodeToString=0)
return ret

_prop_map_get_ = {
}
_prop_map_put_ = {
}
Post by Mark Hammond
Post by Nathan Edwards
from win32com.client import Dispatch
Dispatch('Analyst.FMANWiffFileControl.1')
...
com_error: (-2147467262, 'No such interface supported', None, None)
Post by Mark Hammond
Post by Nathan Edwards
Dispatch('Analyst.FMANWiffFileControl')
...
com_error: (-2147467262, 'No such interface supported', None, None)
Post by Mark Hammond
Post by Nathan Edwards
Dispatch('Analyst.IFMANWiffFileControl')
...
com_error: (-2147221005, 'Invalid class string', None, None)

Why does this CoClass get created with the .1 after it? And why can't I
create an interface to the FMANWiffFileControl object?

Thanks,

nathan
--
Nathan Edwards, Ph.D.
Center for Bioinformatics and Computational Biology
3119 Agriculture/Life Sciences Surge Building #296
University of Maryland, College Park, MD 20742-3360
Phone: +1 301-405-9901
Email: ***@umiacs.umd.edu
WWWeb: http://www.umiacs.umd.edu/~nedwards
Loading...