2009-11-25 9 views
6

मैं निम्न विधि के साथ एक COM घटक का उपयोग करने की कोशिश कर रहा हूं:वैरिएंट्स के पॉइंटर्स का सुरक्षा कैसे बनाएं?

HRESULT _stdcall Run(
    [in] SAFEARRAY(BSTR) paramNames, 
    [in] SAFEARRAY(VARIANT *) paramValues 
    ); 

मैं c/C++ paramValues ​​सरणी में कैसे बना सकता हूं?

उत्तर

6

परिभाषा SAFEARRAY (VARIANT *) परिभाषा बिल्कुल सही नहीं है। इसे एक आईडीएल में सुरक्षित (वारेंट) के रूप में घोषित किया गया है, लेकिन सुरक्षा को लॉक करने से उपलब्ध पॉइंटर वास्तव में एक वैरिएंट * है। यदि आप एक पल के लिए इस बारे में सोचते हैं, तो इसे और अधिक समझना चाहिए। एक सुरक्षित (सूचकांक) का सूचक सूचक सूचक संभवतः अपने भौतिक स्थान में एक संपूर्ण वैरिएंट फिट नहीं कर सकता है, इसलिए कम से कम, यह एक सूचक को स्टोर करने में सक्षम होना चाहिए जिसका उपयोग वैरिएंट की सरणी में अनुक्रमित करने के लिए किया जा सकता है।

यदि आप <wtypes.h> पर देखते हैं, तो कहीं पंक्ति 1110+ के बारे में आपको VT_ गणना परिभाषाएं दिखाई देगी। यह भी दिखाया गया है कि VT_VARIANT वास्तव में वैरिएंट * का तात्पर्य है। [एस] टैग भी सुरक्षित हैं जो सुरक्षित हैं कि सुरक्षा में कौन सी चीजें दिखाई दे सकती हैं।

/* 
* VARENUM usage key, 
* 
* * [V] - may appear in a VARIANT 
* * [T] - may appear in a TYPEDESC 
* * [P] - may appear in an OLE property set 
* * [S] - may appear in a Safe Array 
* 
* 
* VT_EMPTY   [V] [P]  nothing 
* VT_NULL    [V] [P]  SQL style Null 
* VT_I2    [V][T][P][S] 2 byte signed int 
* VT_I4    [V][T][P][S] 4 byte signed int 
* VT_R4    [V][T][P][S] 4 byte real 
* VT_R8    [V][T][P][S] 8 byte real 
* VT_CY    [V][T][P][S] currency 
* VT_DATE    [V][T][P][S] date 
* VT_BSTR    [V][T][P][S] OLE Automation string 
* VT_DISPATCH   [V][T] [S] IDispatch * 
* VT_ERROR   [V][T][P][S] SCODE 
* VT_BOOL    [V][T][P][S] True=-1, False=0 
* VT_VARIANT   [V][T][P][S] VARIANT * 
... (remaining definitions omittted) 
*/ 

हेडर फ़ाइल की प्रतिलिपि यहां एक लिंक है।

wtypes.h at DOC.DDART.NET

यहां से कार्यवाही, तो आप बस एक SAFEARRAY VT_VARIANT का एक संस्करण प्रकार के साथ, घोषणा करेंगे तो उपादानों के रूप में pvData इलाज * जब सरणी ताला लगा। नमूना Win32 कंसोल ऐप के लिए स्रोत कोड यहां दिया गया है जो आपके फ़ंक्शन के समान घोषणा से मेल खाने वाले फ़ंक्शन को कॉल करके इसे प्रदर्शित करता है।

#include "stdafx.h" 
#include "SFAComponent.h" 
#include "SFAComponent_i.c" 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    ::CoInitialize(NULL); 

    SAFEARRAYBOUND nameBounds; 
    nameBounds.cElements = 2; 
    nameBounds.lLbound = 0; 
    LPSAFEARRAY psaNames = SafeArrayCreate(VT_BSTR, 1, &nameBounds); 

    BSTR bstrApple = SysAllocString(L"apple"); 
    BSTR bstrOrange = SysAllocString(L"orange"); 

    SafeArrayLock(psaNames); 
    BSTR *nameArray = (BSTR *)psaNames->pvData; 
    nameArray[0] = bstrApple; 
    nameArray[1] = bstrOrange; 
    SafeArrayUnlock(psaNames); 

    SAFEARRAYBOUND valueBounds; 
    valueBounds.cElements = 2; 
    valueBounds.lLbound = 0; 
    LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &valueBounds); 

    SafeArrayLock(psaValues); 
    VARIANT *valueArray = (VARIANT *)psaValues->pvData; 
    VariantClear(&valueArray[0]); 
    VariantClear(&valueArray[1]); 
    valueArray[0].vt = VT_BSTR; 
    valueArray[0].bstrVal = SysAllocString(L"hello"); 
    valueArray[1].vt = VT_I4; 
    valueArray[1].iVal = 42; 

    { 
    CComPtr<ITestReader> p; 
    p.CoCreateInstance(CLSID_TestReader); 
    p->Run(psaNames, psaValues); 
    p.Release(); // not explicitly necessary. 
    } 

    SafeArrayDestroy(psaValues); 
    SafeArrayDestroy(psaNames); 

    ::CoUninitialize(); 

    return 0; 
} 

घटक इस परीक्षण एप्लिकेशन द्वारा नामक एक ATL dll परियोजना बनाने, और 'TestReader' नामक एक सरल ATL वस्तु जोड़कर बनाया जा सकता है।

ITestReader के लिए आईडीएल यहां है।

[ 
    object, 
    uuid(832EF93A-18E8-4655-84CA-0BA847B52B77), 
    dual, 
    nonextensible, 
    helpstring("ITestReader Interface"), 
    pointer_default(unique), 
    oleautomation 
] 
interface ITestReader : IDispatch{ 
    [id(1), helpstring("method Run")] HRESULT Run([in] SAFEARRAY(BSTR) paramNames, [in] SAFEARRAY(VARIANT) paramValues); 
}; 

सदस्य समारोह आईडीएल घोषणा करने के लिए इसी बस SAFEARRAY * (या LPSAFEARRAY) तर्क लेता है।

public: 
    STDMETHOD(Run)(LPSAFEARRAY paramNames, LPSAFEARRAY paramValues); 

यहां विधि का मुख्य भाग है। ब्रेवटी के लिए एक सहायक फ़ंक्शन PrintVariant() भी शामिल है।

void PrintVariant(VARIANT *pV) 
{ 
    switch(pV->vt) 
    { 
    case VT_BSTR: 
    wprintf(L" BSTR: %s\r\n", pV->bstrVal); 
    break; 
    case VT_I4: 
    wprintf(L" Integer: %d\r\n", pV->iVal); 
    break; 
    default: 
    wprintf(L" Unrecognized Type: vt=%d\r\n", pV->vt); 
    break; 
    } 
} 

STDMETHODIMP CTestReader::Run(LPSAFEARRAY paramNames, LPSAFEARRAY paramValues) 
{ 
    SafeArrayLock(paramNames); 
    SafeArrayLock(paramValues); 
    BSTR *nameArray = (BSTR *)paramNames->pvData; 
    VARIANT *valueArray = (VARIANT *)paramValues->pvData; 

    wprintf(L"Item 0 is %s, variant type %d\r\n", nameArray[0], valueArray[0].vt); 
    PrintVariant(&valueArray[0]); 
    wprintf(L"Item 1 is %s, variant type %d\r\n", nameArray[1], valueArray[1].vt); 
    PrintVariant(&valueArray[1]); 

    SafeArrayUnlock(paramNames); 
    SafeArrayUnlock(paramValues); 

    return S_OK; 
} 
+0

मैं वीबी स्क्रिप्ट से SAFEARRAY विधि से तारों की सरणी कैसे पास कर सकता हूं ? क्या आप एक उदाहरण पोस्ट कर सकते हैं? –

8

भविष्य पाठकों द्वारा संदर्भ के लिए ऊपर उत्तर देने के लिए जोड़ा जा रहा है: आईडीएल में, SAFEARRAY(...) एक सरणी वर्णनकर्ता के लिए सूचक का मतलब है। लेकिन सी ++ में, SAFEARRAY का मतलब एक सरणी वर्णनकर्ता है। तो आईडीएल का SAFEARRAY(...) वास्तव में सी ++ का SAFEARRAY * है। इससे मुझे कोई अंत नहीं हुआ। चीजों को और भी दिलचस्प बनाने के लिए, वीबी हमेशा संदर्भ द्वारा सरणी पास करता है। तो वीबी के () As Long सी ++ में SAFEARRAY<int32_t> ** है। (मुझे नहीं पता कि वास्तव में एक सामान्य रूप से उपयोग किया जाने वाला हेडर है जो आपको टेम्पलेट पैरामीटर के रूप में निर्दिष्ट करने की अनुमति देता है, लेकिन मैंने इसे स्पष्टता के लिए डाला।)

+0

आईडीएल संदर्भ में SAFEARRAY और SAFEARRAY सी/सी ++ संरचना के बीच मतभेदों पर टिप्पणी के लिए +1 – meklarian

संबंधित मुद्दे