在Python中传递参数给COM对象
我正在写一个Python脚本来控制一个COM对象。官方文档是用C#、VB和C语言写的。文档(用VB写的)内容如下:
Public Function GetDATA {
ByVal vecRecords() As DATAType,
ByRef Time As String,
optional ByVal filter1 As String,
optional ByVal kind2 As Kind = KindAll,
optional ByVal type1 As Types = TypeAll
) As Long
根据我的理解,第一个参数是返回值,在Python中可以正常返回。最后三个参数是枚举类型(转换成数字),但无论如何都是可选的。我现在的问题是,"ByRef Time As String"这个参数我应该传什么?
我的代码是:
>>> from win32com.client import Dispatch
>>> Obj = Dispatch("Service.Foo")
>>> Obj.Function()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Python27\lib\site-packages\win32com\gen_py\48C77DB1-D9E0-45B8-9992-C9
2B047CC700x0x1x0.py", line 399, in Function
, LastTime, BNO, kind, madadType)
File "D:\Python27\lib\site-packages\win32com\client\__init__.py", line 456, in
_ApplyTypes_
self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args),
pywintypes.com_error: (-2147023170, 'The remote procedure call failed.', None, None)
我还运行了:
>>> Obj.Function()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Python27\lib\site-packages\win32com\gen_py\48C77DB1-D9E0-45B8-9992-C9
2B047CC700x0x1x0.py", line 399, in Function
, LastTime, BNO, kind, madadType)
File "D:\Python27\lib\site-packages\win32com\client\__init__.py", line 456, in
_ApplyTypes_
self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args),
TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a bufferobject.
还有:
>>> a= ("00000000","00000000",-1,-1)
>>> Obj.Function(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Python27\lib\site-packages\win32com\gen_py\48C77DB1-D9E0-45B8-9992-C9
2B047CC700x0x1x0.py", line 399, in Function
, LastTime, BNO, kind, madadType)
File "D:\Python27\lib\site-packages\win32com\client\__init__.py", line 456, in
_ApplyTypes_
self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args),
MemoryError: CreatingSafeArray
返回值不大,所以我真的不明白最后一个。
系统信息:
Windows 7 64位。
Python 2.7.2 32位(从以管理员身份启动的命令行运行,因为这个COM对象需要这样)。
有没有简单的方法来发现这个函数需要什么?
提前感谢!
Marbs。
[编辑]
我给你一个可以工作的C#代码片段:
System.Array tempArray;
string lTime = "00000000";
Res = Obj.getDATA(out tempArray, ref lTime, "0", Obj.type1, Obj.type2);
其中Obj.type1和Obj.type2是来自Obj本身的枚举类型。它们都转换成-1(一个整数)。
2 个回答
如果你在解决一个很难的问题时遇到麻烦,可以试着先做一些简单的事情,这可能会让你对那个难题有一些新的理解。
听起来你是在用Python调用一个你不太熟悉的COM API,而这个API使用了一些比简单的字符串和整数更复杂的数据类型。为什么不试试用像C#或VB这样的.Net语言写一个简单的客户端呢?这样你就能了解这个库需要什么样的值了。可能在这些语言中还有一些现成的例子,你可以直接复制并运行。然后,你可以根据这个工作示例把它转换成Python。
你还可以考虑使用IronPython,它已经与.Net兼容,这样可能会让你的开发过程更简单。
最后,还有一种与.Net兼容的Python风格语言叫做Boo。我以前用它为客户开发了一些简单的工具,因为它的代码写起来和Python很像,但可以生成独立的.DLL或.EXE文件。虽然这个项目在过去一年多没有明显的更新,但在几年前我开发一些SOAP客户端和服务器代码时,这种语言对我非常有帮助。
在写VB代码的时候,如果使用了ByRef
这个选项,比如在我提到的解密函数中用到的ByRef Time As String,
,那么这个函数会直接修改传入的变量,就像C++中的指针一样。
这个COM对象试图去修改一些它没有权限更改的内存区域。这就是我在Python中运行时遇到内存错误的原因。