[python-win32] Why does a python COM server return different data to VBA and Python clients?

dived38295 at mypacks.net dived38295 at mypacks.net
Mon Apr 16 19:01:03 CEST 2012

Thanks for the reply. I forgot that I had copied Method2 and Method3 from a thread I saw from 2006, 2006-October/005094. That thread just seemed to die without resolution.

I was going to include the differences but I determined why it failed. According to the Microsoft support website "By default, VBA passes arguments by reference."

I would have expected VBA to make an "[in]" parameter use ByVal but that didn't happen, so I did some digging. I found that my example was returning more data than expected. If I removed the extra return value it works and the "[in]" parameter from VBA is not overwritten.
If I forward declare the method in VBA then it detects the extra data and reports an error. I find the VBA behavior a bit confusing.

For anyone interested you can see this behavior using the Pippo test with the following changes:

I added the following line to the "pippo.idl" interface IPippo:
        [id(4), helpstring("method Method3")] HRESULT Method3([in] long in1, [in, out] long *inout1, [out, retval] long *val);
        [id(99), helpstring("method Method4")] HRESULT Method4([in] long in1, [in, out] long *inout1, [out, retval] long *val);

I added the following lines to the pippo_server.py class CPippo. Note that Method 4 is returning an extra value.
    def Method3(self, in1, inout1):
        return( 1010,1011 )
    def Method4(self, in1, inout1):
        return( 1010,1011,1012 )
Execute the following VBA code (Excel, or Word have VBA in macros):
	Private Declare Function Pippo_Method3 Lib "TESTSERVERLib.Pippo" (ByVal in1 As Long, inout1 As Long) As Long
	Sub TestPippo()
		  Dim obj As Object
		  Dim in1 As Long
		  Dim inout1 As Long

		  Set obj = CreateObject("Python.Test.Pippo")
		  in1 = -1
		  inout1 = -2
		  retval3 = obj.Method3(in1, inout1)
		  outputMessage = outputMessage & "    Forward declared - Method 3 retval3 = " & retval3 & " inout1 = " & inout1 & " in1 = " & in1 & vbCrLf

		  in1 = -1
		  inout1 = -2
		  retval4 = obj.Method4(in1, inout1)
		  outputMessage = outputMessage & "Not Forward declared - Method 4 retval4 = " & retval4 & " inout1 = " & inout1 & " in1 = " & in1 & vbCrLf

		  MsgBox outputMessage

 End Sub		

If you call Method4 from a Python client then it only sees a tuple with 2 elements as expected by the idl. It did seem odd that the VBA saw more data so I guess the Python server method return data is not checked against the registered tlb and just passes the data directly through to the COM client.


More information about the python-win32 mailing list