Getting a ValueError with comtypes

winkatl1213 at yahoo.com winkatl1213 at yahoo.com
Thu Oct 5 12:41:19 EDT 2006


Thomas,

Thanks a ton for the quick response.

I called GetModule('quartz.dll'), and now I can at least call
IMediaControl::Run.  I get another error, but that's my problem (I
don't have the graph set correctly yet).

You mentioned that you sometimes create a type library for creating the
interface wrappers.

Would you mind sharing with me how you do this?

I seem to recall a thread on ctypes-users where you were looking for a
method to do this.  I can't seem to locate what you conclusion was.

By the way, I've been using ctypes and comtypes quite a bit lately, and
I just wanted to say that they are both excellent.

Now if only I had an equivalent way to access C++ dlls, I'd no longer
have to write typemaps in SWIG.

While I'm at it, I thought I would ask you a separate completely
unrelated question.

I have a C++ library wrapped with SWIG.  One member function takes a
void* to a buffer.

I want to allocate this buffer using ctypes and pass it to my SWIG
wrapper, but I've been struggling to get it to work.

I tried passing in the addressof, and then casting it back in my SWIG
wrapper, but this doesn't work.  Do you have any suggestions on this?

I've also thought about using a numpy array, since this is supported in
both SWIG and ctypes.

Thanks again for your help.,

Jeff

Thomas Heller wrote:
> winkatl1213 at yahoo.com schrieb:
> > Hello,
> >
> > I am working with comtypes to interface Microsoft's DirectShow library.
>
> Cool, another one using comtypes!
>
> > First, I found a Type Library on the internet that was created for
> > accessing DirectShow from .NET.  It seems that DirectShow only comes
> > with IDL files and no type library.
>
> What I sometimes do is to compile the IDL files into a typelib just
> for creating the comtypes interface wrappers.  This may be somewhat
> dangerous because these typelibs should *not* be registered by accident,
> so that they do not conflict with other typelibs.
>
> Then, I found out with oleview that on my system the IMediaControl interface
> is described in the 'ActiveMovie control type library (Ver 1.0)',
> in c:\windows\system32\quartz.dll.  So I was able to create the wrapper
> by calling comtypes.client.GetModule("quartz.dll") - it seems that windows
> searches the $PATH to find type libraries.
>
> > This got me started.
> >
> > The following line imports the typelibrary and automatically generates
> > a wrapper module for DirectShow.
> >
> > ds = comtypes.client.GetModule('DirectShow.tlb')
> >
> > Next, I can basically start with something like this:
> >
> > graph = comtypes.CoCreateInstance(CLSID_FilterGraph, ds.IGraphBuilder,
> > comtypes.CLSCTX_INPROC_SERVER)
> >
> > I had to create the CLSID_FilterGraph parameter myself by doing the
> > following:
> >
> > CLSID_FilterGraph =
> > comtypes.GUID('{e436ebb3-524f-11ce-9f53-0020af0ba770}')
> >
> > One of the first issues I ran into was that the type library I found on
> > the web didn't expose the IMediaControl interface.  So, using the
> > generated wrapper as a template, I created my own wrapper:
> >
> > class IMediaControl(comtypes.IUnknown):
> >     _case_insensitive_ = True
> >     _iid_ = comtypes.GUID('{56A868B1-0AD4-11CE-B03A-0020AF0BA770}')
> >     _idlflags_ = []
> > IMediaControl._methods_ = [
> >     COMMETHOD([], HRESULT, 'Run'),
> >     COMMETHOD([], HRESULT, 'Pause'),
> >     COMMETHOD([], HRESULT, 'Stop'),
> >     COMMETHOD([], HRESULT, 'StopWhenReady'),
> >     COMMETHOD([], HRESULT, 'GetState',
> >               (['in'], c_long, 'msTimeout'),
> >               (['out'], POINTER(c_int), 'pfs' ))
> > ]
> >
> > This got me further.  Once I defined the interface, I get access to the
> > interface by calling:
> >
> > control = graph.QueryInterface(IMediaControl)
> >
> > This seemed to work.  Once I got everything setup, I tried to use this
> > interface.  For example:
> >
> > control.Run()
> >
> > This generates an exception:
> >
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in ?
> >   File "ds.py", line 462, in play
> >     control.Run()
> > ValueError: Procedure probably called with not enough arguments (4
> > bytes missing)
> >
> > You can get errors like this when using ctypes if you use the wrong
> > calling convention (CDLL versus WINDLL).
> >
> > The method "Run" on the IMediaControl interface doesn't take any
> > arguments.
> >
> > I did notice that some wrapper code uses STDMETHOD versus COMMETHOD,
> > but changing this didn't make any difference.
> >
> > Can anyone explain what might be happening here, or offer some
> > suggestions?
>
> Your mistake here is that IMediaControl derives from IDispatch, not IUnknown.
> So, control.Run() really calls the first IDispatch method, which is
> GetTypeInfoCount(), which takes one argument ;-).
>
> I'm not 100% sure the following code will work for you because I'm using
> a comtypes version that's not yet committed to the repository, but it works
> for me:
>
> from comtypes.client import GetModule, CreateObject
>
> # create and import the interface wrapper
> ds = GetModule("quartz.dll")
>
> # FilgraphManager is what the wrapper shows as coclass,
> # you can pass that to CreateObject instead of a CLSID or ProgID.
> # CreateObject calls QueryInterface for the 'most useful' interface,
> # so usually there's no need to specify the interface you want:
> fg = CreateObject(ds.FilgraphManager)
> 
> # this prints '0'
> print fg.Run()
> 
> Thomas




More information about the Python-list mailing list