[python-win32] Calling an OLE Automation (IDispatch) server which uses "out params"

Dave Calkins dave at kinematics.com
Tue Dec 18 00:46:12 CET 2012


On 12/16/2012 6:17 PM, Mark Hammond wrote:
>
>> I'm the vendor of the object :)  As I mentioned, I just created this
>> small test app which reproduces the issue having just those 3 simple
>> methods.  However, I'm not able to talk to it via Python.
>
> Is the source to this available?
>

Yes, its just a Visual C++ app-wizard generated project.  In Visual C++ 
2010 I used new >> project, selected MFC application, chose a dialog app 
with default settings but I checked the "Automation" checkbox so it 
would set it up as an OLE Automation server.  Once created, in the Class 
view I right-clicked the IMyApp interface and chose Add >> Method.  I 
did this for each method shown earlier.  When you add a method this way, 
it adds it to the IDL and then adds implementation methods in the 
DlgProxy class it creates as part of the project.  Then you just fill in 
the implementation methods that it created for you.

Here is the IDL.

=====
     [ uuid(E85C16AC-7936-4792-8E2A-40537D9FA02B) ]
     dispinterface IMyApp
     {
         properties:

         methods:
             [id(1)] void ShowMessage(BSTR msg);
             [id(2)] void SetSettingValue(BSTR settingName, BSTR 
settingValue);
             [id(3)] void GetSettingValue(BSTR settingName, BSTR* 
settingValue);
     };
=====

Here's the implementation methods it created for the above.  For the 
first two I'm just showing a message box with the passed in args. For 
the third, with the out param, I'm sending back a dummy value to the caller.

=====
void CMyAppDlgAutoProxy::ShowMessage(LPCTSTR msg)
{
     AFX_MANAGE_STATE(AfxGetAppModuleState());

     // TODO: Add your dispatch handler code here
     CString s;
     s.Format(_T("ShowMessage\n\"%s\""), msg);
     AfxMessageBox(s);
}


void CMyAppDlgAutoProxy::SetSettingValue(LPCTSTR settingName, LPCTSTR 
settingValue)
{
     AFX_MANAGE_STATE(AfxGetAppModuleState());

     // TODO: Add your dispatch handler code here
     CString s;
     s.Format(_T("SetSettingValue\nsettingName = \"%s\"\nsettingValue = 
\"%s\""), settingName, settingValue);
     AfxMessageBox(s);
}


void CMyAppDlgAutoProxy::GetSettingValue(LPCTSTR settingName, BSTR* 
settingValue)
{
     AFX_MANAGE_STATE(AfxGetAppModuleState());

     // TODO: Add your dispatch handler code here
     CString s;
     s.Format(_T("%s=testValue123"), settingName);
     *settingValue = s.AllocSysString();
}
=====

The first two methods work great, I can call those from python without 
any problems.

>
> Nope - it should all be good.  For example, check out:
>
> http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/file/8b73631eeee0/com/TestSources/PyCOMTest/PyCOMTest.idl#l193 
>
>
> http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/file/8b73631eeee0/com/TestSources/PyCOMTest/PyCOMImpl.cpp#l133 
>
>
> and (slightly cryptic) Python code which calls it:
>
> http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/file/8b73631eeee0/com/win32com/test/testPyComTest.py#l225 
>
>
> Which shows some "out" param tests (and while there is an inout bstr 
> test, there doesn't seem to be a specific test for an out bstr, so 
> it's still possible you have hit a pywin32 bug)

Thanks for the links.  I'll take a look at them as soon as I can.

>> You indicated that the out params should be converted to a return
>> value.  Why does the MakePy generated method signature not indicate
>> this?  i.e. why does it show 2 arguments?
>
> The makepy signature really just reflects the params passed to the 
> interface itself - hence those params all have default values.
>
>> You said above that pywin32 *will* be passing a second param - a byref
>> bstr.  That suggests to me that there's some other method I need to call
>> which internally calls the real method from pywin32. Where is the method
>> I need to call then?  I don't see any method generated there with only a
>> single arg?
>
> InvokeTypes is what does all the magic - it takes the VT_* values and 
> builds real params in C++, and also builds the tuple (if necessary) 
> which is returned.  The params mainly exist for when the interface is 
> *implemented* by Python rather than when called by Python - the same 
> generated classes are used in both directions.
>

Got it, so I shouldn't expect the actual calling convention to be bound 
to whats in the MakePy code.

> Hope this clarifies...

Yes, thanks for the continued help on this.  I'd love to see this work 
from Python and then be able to provide that as another way to automate 
this app.



More information about the python-win32 mailing list