2014-01-23 58 views

回答

1

此失敗的主要原因是a kludge in comtypes,其中DECIMAL類型未正確定義。因爲它需要64位或8個字節的雙精度浮點數,但實際需要16個字節或128個位,因此實際需要的值爲struct

對於當前的目的,你可以使用的DECIMAL任何定義,有適當的大小相處,所以這裏是一個:

# comtypes/automation.py 
class tagDEC(Structure): 
    _fields_ = [("wReserved", c_ushort), 
       ("scale", c_ubyte), 
       ("sign", c_ubyte), 
       ("Hi32", c_ulong), 
       ("Lo64", c_ulonglong)] 
DECIMAL = tagDEC 


# comtypes/tools/tlbparser.py 
DECIMAL_type = typedesc.Structure("DECIMAL", 
            align=alignment(automation.DECIMAL)*8, 
            members=[], bases=[], 
            size=sizeof(automation.DECIMAL)*8) 

然而,你可能會難倒因爲便攜式設備API中的某些方法不適合自動化。

例如,IPortableDeviceManager::GetDevices具有unique attribute(在實際的PortableDeviceApi.idl文件中,不在文檔中),這意味着您實際上可以通過NULL。但是,type libraries don't capture this information

相同的參數實際上可以是一個大小由下一個參數決定的數組。同樣,類型庫不支持這個,只有單對象頂級指針。此外,實際的IDL沒有size_is attribute,這意味着方法調用不會在公寓間工作,或者此接口具有自定義封送拆分器。

快速查看便攜式設備API可以看出,該模式一直適用於實際使用數組的其他方法。看起來好像熟悉Win32 API的人做了這些方法,因爲當數組參數爲NULL時,有一堆Win32函數被重載以獲取某個數組的大小。這根本不是通常的COM方式,最好有兩種方法(知道元素數量,分配足夠的內存並獲取它們之間具有相同的競爭條件),只有out參數的單一方法(沒有競爭條件,但沒有控制內存使用)或使用枚舉(例如IEnumPortableDevice,更難但更清潔)。

無論如何,您可以將comtypes.client.GetModule("…PortableDeviceApi.dll")生成的代碼作爲第一步。然後,按照these instructions的說法使Python方法以文檔化的方式實際調用COM方法。例如,IPortableManager::GetDevices將成爲:

# comtypes/gen/_1F001332_1A57_4934_BE31_AFFC99F4EE0A_0_1_0.py 
class IPortableDeviceManager(comtypes.gen._00020430_0000_0000_C000_000000000046_0_2_0.IUnknown): 
    # ... 
    def GetDevices(self): 
     cPnPDeviceIDs = c_ulong(0) 
     self.__com_GetDevices(None, byref(cPnPDeviceIDs)) 
     PnPDeviceIDs = (WSTRING * cPnPDeviceIDs.value)() 
     self.__com_GetDevices(PnPDeviceIDs, byref(cPnPDeviceIDs)) 
     deviceIDs = PnPDeviceIDs[:cPnPDeviceIDs.value] 
     for i in range(cPnPDeviceIDs.value): 
      windll.ole32.CoTaskMemFree(cast(PnPDeviceIDs, POINTER(c_void_p))[i]) 
     return deviceIDs 
# ... 
IPortableDeviceManager._methods_ = [ 
    COMMETHOD([], HRESULT, 'GetDevices', 
       (['in'], POINTER(WSTRING), 'pPnPDeviceIDs'), 
       (['in'], POINTER(c_ulong), 'pcPnPDeviceIDs')), 
    # ... 

下面的測試運行成功,雖然它在我的情況下返回一個空列表,因爲我沒有任何連接的設備現在:

# First run 
import os 
from comtypes.client import GetModule 
GetModule(os.getenv("WINDIR") + "\\system32\\PortableDeviceApi.dll") 

# Quit python 
# Edit comtypes/gen/_1F001332_1A57_4934_BE31_AFFC99F4EE0A_0_1_0.py 

# Subsequent runs 
from comtypes.client import CreateObject 
from comtypes.gen.PortableDeviceApiLib import * 
CreateObject(PortableDeviceManager).GetDevices() 

我如果不能進一步清除comtypes,就無法提供更多的幫助。我建議你聯繫它的作者或維護者。

編輯:同時,我在0123F在SourceForge站點。由於該項目正在從SourceForge轉換而來,似乎已被忘記,but it wasn'there too)。

你從那以後試過導入模塊嗎?