Create SAFEARRAY of Strings in Python

5.6k views Asked by At

I'm trying to call a COM method that requires a SafeArray of Strings to be passed as reference, which is then filled up with the method results. This is the code in VBA, which works flawlessly:

dimr RC as New RAS41.HECRASController
RC.Project_Open "c:\myProj.prj"
dim numMessages as Long
dim messages() as String
RC.Compute_CurrentPlan( numMessages, messages())

Now, I'm trying to do the same from with Python 3.4, using the win32com module. However, I'm stuck at trying to create the second parameter with the correct type, which according to combrowse.py should be "Pointer SafeArray String".

This was my first attempt:

import win32com
RC =  win32com.client.Dispatch("RAS41.HECRASController")
RC.Project_Open("c:\\myProj.prj")
numMessages = 0
messages = []
RC.Compute_CurrentPlan(numMessages, messages)

I also tried constructing that variable as

messages = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_BSTR, [])

but it didn't work either. Error messages look like this:

Traceback (most recent call last):
File "<pyshell#101>", line 1, in <module>
  print(o.Compute_CurrentPlan(1,b))
File "<COMObject RAS41.HECRASController>", line 3, in Compute_CurrentPlan
File "C:\Python34\lib\site-packages\win32com\client\dynamic.py", line 282, in _ApplyTypes_
result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.
2

There are 2 answers

0
Paul G. On

Make sure that you python variables are in the right format (Long and String). Try to use something like the following to get the variable types in shape:

messages = ['']
RC.Compute_CurrentPlan(long(numMessages), messages)

To be more flexible with your program you should check the variable types prior to the win32 call.

0
KHarris On

I realize this is an old question, but I ran into this issue and wanted to share the resolution. I was having issues defining the type of data for the first two arguments, but simply setting them to None works and your number of messages and compute messages are reported (I checked by assigning text = hec.Compute_CurrentPlan(None, None, True) and then print(test)). The third argument is Blocking Mode, set to True, meaning that the RAS computation will complete before moving to the next line of code. I am using Python 3.10.4 and HEC-RAS version 6.3.

import win32com.client
hec = win32com.client.Dispatch('RAS630.HECRASController')
hec.Project_Open(r"C:\myproj.prj")
hec.ShowRAS()
hec.Compute_CurrentPlan(None, None, True)
hec.QuitRAS()