2013-04-29 59 views
3

我在使用IDispatch.Invoke調用具有浮點參數和浮點結果的函數時遇到問題。如何使用IDispatch.Invoke調用接收浮點值的函數?

這裏有一個最小的再現:

#include <atlbase.h> 
#include <comutil.h> 

int main(int argc, char* argv[]) 
{ 
    CoInitialize(NULL); 
    CComPtr<IDispatch> wordapp; 
    if (SUCCEEDED(wordapp.CoCreateInstance(L"Word.Application", NULL, CLSCTX_LOCAL_SERVER))) 
    { 
     CComVariant result; 
     CComVariant centimeters((float)2.0); 
     CComVariant retval = wordapp.Invoke1(L"CentimetersToPoints", &centimeters, &result); 
    } 
    return 0; 
} 

我使用ATL CComPtr使事情更清潔。但是這是一個非常寬鬆的包裝IDispatch.Invoke

當我運行這個時,對Invoke1的調用失敗並返回E_FAIL

我懷疑問題與使用浮點參數和/或返回值有關。如果我叫不使用這些值的函數的調用成功:

CComVariant retval = wordapp.Invoke0(L"ProductCode", &result); 

我注意到,如果我調用函數從VBS,或者從PowerShell中,它成功。我假設他們都使用後期限制IDispatch,所以這表明我至少可以嘗試我所嘗試的。

那麼,如何使用IDispatch來調用這個函數呢?

回答

5

那麼,這是一個頭部劃痕。這種「方法」的文檔非常具有誤導性,它不是一種方法。它的行爲更像索引屬性,需要DISPATCH_METHOD | DISPATCH_PROPERTYGET標誌。 CComPtr不支持,你需要手動旋轉。此代碼工作:

CComVariant result; 
    CComVariant centimeters((float)2.0); 
    DISPID dispid; 
    LPOLESTR name = L"CentimetersToPoints"; 
    HRESULT hr = wordapp->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); 
    assert(SUCCEEDED(hr)); 

    DISPPARAMS dispparams = { &centimeters, NULL, 1, 0}; 
    hr = wordapp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, 
      DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparams, &result, nullptr, nullptr); 
    assert(SUCCEEDED(hr)); 
+1

真的,你是一個天才。非常感謝。 – 2013-04-29 20:04:40

+0

它可能不應該在文檔中,而應該在一些通用的觀察。看看這裏請:http://pastebin.ca/2369858看來,德爾福RTL增加了每個方法的get-property標誌與返回值和零參數。最明顯的解決方案是擦拭arg-count檢查並始終將方法轉換爲method + prop-getter,但是我無法預測這會導致更大的後果,它是否會打破其他一些方法調用,獲得者標誌? – 2013-04-30 09:33:58

+0

*有些語言無法區分檢索屬性和調用方法。在這種情況下,您應該設置標誌DISPATCH_PROPERTYGET和DISPATCH_METHOD。* http://msdn.microsoft.com/en-us/library/windows/desktop/ms221486.aspx是否意味着Method-or-getter始終是安全的後退和額外的「ArgCount == 0」後衛應該被認爲是Delphi RTL中的一個錯誤? @DavidHeffernan:QC-able? – 2013-04-30 09:36:01

相關問題