, , , . / IDL . :
HRESULT Method1([in] short rgs[8]);
(fixed array) IDL . 16 (8 * sizeof (short)) ORPC- , . ORPC- , , . 7.2.
, , .
, 8. (shorts), , :
void f(IFoo *pFoo) { short rgs[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; pFoo->Method1(rgs); }
, , , . , , / . , , .
, IDL ( NDR) . (conformant). , , , (conformance) , , . 7.3. , - , .
, IDL [size_is]:
HRESULT Method2([in] long cElems, [in, size_is(cElems)] short rgs[*]);
HRESULT Method3([in] long cElems, [in, size_is (cElems)] short rgs[]);
HRESULT Method4([in] long cElems, [in, size_is(cElems)] short *rgs);
. :
void f(IFoo *pFoo) { short rgs[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; pFoo->Method2(8, rgs); }
, [size_is] , , , . , IDL- :
HRESULT Method5([in] long arg1, [in] long arg2, [in] long arg3, [in, size_is(arg1 ? (arg3+1) : (arg1 & arg2))] short *rgs);
, ( , ++ --), [size_is].
[size_is] , - , :
typedef struct tagCOUNTED_SHORTS { long cElems; [size_is(cElems)] short rgs[]; } COUNTED_SHORTS; HRESULT Method6([in] COUNTED_SHORTS *pcs);
, :
void SendFiveShorts (IFoo *pFoo) { char buffer [sizeof (COUNTED_SHORTS) + 4 * sizeof (short)]; COUNTED_SHORTS& rcs = *reinterpret_cast<COUNTED_SHORTS*>(buffer); rcs.cElems = 5; rcs.rgs[0] = 0; rcs.rgs[1] = 1; rcs.rgs[2] = 2; rcs.rgs[3] = 3; rcs.rgs[4] = 4; pFoo->Method6(&rcs); }
IDL [max_is], [size_is]. [size_is] , ; [max_is] ( , ). , :
HRESULT Method7([in, size_is(10)] short *rgs); HRESULT Method8([in, max_is(9)] short *rgs);
, [size_is] , , . , , , , .
, . . , :
HRESULT Method9([in] long cMax, [out, size_is(cMax)] short *rgs);
:
void f(IFoo *pFoo) { short rgs[100]; pFoo->Method9(100, rgs); }
:
HRESULT CFoo::Method9(long cMax, short *rgs) { for (long n = 0; n < cMax; n++) rgs[n] = n * n; return S_OK; }
, ? , cMax/2 , , , cMax . , , IDL NDR , (varying array).
, , , . . , , IDL [length_is]. [size_is], , [length_is] . IDL:
HRESULT Method10([in] long cActual, [in, length_is(cActual)] short rgs[1024]);
cActual, (variance) , . (region) , , IDL NDR [first_is], , . , , . , [size_is] [max_is], [length_is] [last_is], . :
HRESULT Metnod11([in, first_is(2), length_is(5)] short rgs(8]); HRESULT Method12([in, first_is(2), last_is(6)] short rgs[8]);
, . , , .
, . , . 7.4, , , . , , (" "). , . , . , , , .
, / . , ( , , - ).
, IDL, NDR ( ), ( ) [size_is] [length_is]. , (open) . , :
HRESULT Method13([in] cMax, [in] cActual, [in, size_is(cMax), length_is(cActual)] short rgs[]);
HRESULT Method14([in] cMax, [in] cActual, [in, size_is(cMax), length_is(cActual)] short rgs[*]);
HRESULT Method15([in] cMax, [in] cActual, [in, size_is(cMax), length_is(cActual)] short *rgs);
:
void f(IFoo *pFoo) { short rgs[8]; rgs[0] = 1; rgs[1] = 2; pFoo->Method13(8, 2, rgs); }
. 7.5, , . , , . , , , .
. / , , , . IDL :
HRESULT Method16([in] long cMax, [out] long *pcActual, [out, size_is(cMax), length_is(*pcActual)] short *rgs);
:
void f(IFoo *pFoo) { short rgs[8]; long cActual; pFoo->Method16(8, &cActual, rgs); // .. process first cActual elements of rgs // .. cActual rgs }
:
HRESULT CFoo::Method16(long cMax, long *pcActual, short *rgs) { *pcActual = min(cMax,5); // only write 1st 5 elems // for (long n = 0; n < *pcActual; n++) rgs[n] = n * n; return S_OK; }
, .
/ , . , / :
HRESULT Method17([in] long cMax, [in, out] long *pcActual, [in, out, size_is(cMax), length_is(*pcActual)] short *rgs);
:
void f(IFoo *pFoo) { short rgs[8]; rgs[0] = 0; rgs[1] = 1; long cActual = 2; pFoo->Method17(8, &cActual, rgs); // .. process first cActual elements of rgs // .. cActual rgs }
, :
HRESULT Method18([in] long cElems, [in, out, size_is(cElems)] short *rgs);
, .
. :
void g(short **arg1);
, . , :
void g(short **arg1) { // return ptr to static // static static short s; *arg1 = &s; }
, , 100 :
void g(short **arg1) { // square 100 shorts by ref // 100 for (int n = 0; n < 100; n++) *(arg1[n]) *= *(arg1[n]); }
, , :
void g(short **arg1) { // square 100 shorts // 100 for (int n = 0; n < 100; n++) (*arg1)[n] *= (*arg1)[n]; }
IDL , - .
IDL [size_is] [lengtn_is] , . , , , . , , :
HRESULT Method19([in] short **pps);
:
pps -> *pps-> **pps
, , IDL:
HRESULT Method20([in, size_is(3)] short **rgps);
:
rgps -> rgps[0] -> *rgps[0] rgps[1] -> *rgps[1] rgps[2] -> *rgps[2]
, , IDL:
HRESULT Method21([in, size_is(,4)] short **pprgs);
:
pprgs -> pprgs -> (pprgs)[0] (pprgs)[1] (pprgs)[2] (pprgs)[3]
, , :
HRESULT Method22([in, size_is(3,4)] short **rgrgs);
:
rgrgs -> rgrgs[0] -> rgrgs[0][0] rgrgs[0][1] rgrgs[0][2] rgrgs[0][3] rgrgs[1] -> rgrgs[1][0] rgrgs[1][1] rgrgs[1][2] rgrgs[1][3] rgrgs[2] -> rgrgs[2][0] rgrgs[2][1] rgrgs[2][2] rgrgs[2][3]
, , , , , .
, IDL ; . , , IDL :
HRESULT Method23([in] short rgrgs[3][4]);
, , .
[size_is]:
HRESULT Method24([in, size_is(3)] short rgrgs[][4]);
, .
, [size_is], [length_is] , . , , , / wcslen strlen. , IDL :
HRESULT Method24([in, size_is(wcslen(wsz) + 1)] const OLECHAR *wsz);
, IDL , xxxlen . :
HRESULT Method25([in, string] const OLECHAR *wsz);
:
HRESULT Method26([in, string] const OLECHAR wsz[]);
/ , , . IDL:
HRESULT Method27([in, out, string] OLECHAR *pwsz);
:
void f(IFoo *pFoo) { OLECHAR wsz[1024]; wcscpy(wsz, OLESTR("Hello")); pFoo->Method27(wsz); // .. process updated string // .. }
, , , ( ). :
HRESULT CFoo::Method27(OLECHAR *wsz) { DisplayString(wsz); // wsz only can hold 6 characters! // wsz 6 ! wcscpy(wsz, OLESTR("Goodbye")); return S_OK; }
wcslen(OLESTR("Hello")+1), , - , " " , ( , ). , , , , , Unicode. IDL :
HRESULT Method28([in] long cchMax, [in, out, string, size_is(cchMax)] OLECHAR *wsz);
:
void f(IFoo *pFoo) { OLECHAR wsz[1024]; wcscpy(wsz, OLESTR("Hello")); pFoo->Method28(1024, wsz); // .. process updated string // .. }
c [in, out, string] , , , . , , .
API- , , , , . . ( , ) . , , . Windows SDK, , , :
void Show(HWND hwndEdit) { TCHAR sz[1024]; GetWindowText(hwndEdit, sz, 1024); MessageBox(0, sz, _TEXT("Hi!"), MB_OK); }
, Show , 1024 . ? . , :
void Show(HWND hwndEdit) { int cch = GetWindowTextLength(hwndEdit); TCHAR *psz = new TCHAR[cch+1]; GetWindowText(hwndEdit, psz, cch); MessageBox(0, sz, _TEXT("Hi!"), MB_OK); delete[] psz; }
, GetWindowTextLength, GetWindowText? , , .
, , HWND, . HWND, . , , , , , , , . [out]- , - . , . , , , , . , IDL:
HRESULT Method29([out, string] OLECHAR **ppwsz);
:
HRESULT CFoo::Method29(OLECHAR **ppwsz) { const OLECHAR wsz[] = OLESTR("Goodbye"); int cb = (wcslen(wsz) + 1) * sizeof(OLECHAR); *ppwsz = (OLECHAR*)CoTaskMemAlloc(cb); if (*ppwsz == 0) return E_OUTOFMEMORY; wcscpy(*ppwsz, wsz); return S_OK; }
:
void f(IFoo *pFoo) { OLECHAR *pwsz = 0; if SUCCEEDED(pFoo->Method29(&pwsz)) { DisplayString(pwsz); CoTaskMemFree(pwsz); } }
, , , , - , , .
, , C++. , , , Visual Basic . Visual Basic , IDL , SAFEARRAY. SAFEARRAY , , VARIANT. SAFEARRAY SAFEARRAYBOUND:
typedef struct tagSAFEARRAYBOUND { ULONG cElements; // size_is for dimension // size_is LONG lLbound; // min index for dimension (usually 0) // ( 0) } SAFEARRAYBOUND;
SAFEARRAY SAFEARRAYBOUND, :
typedef struct tagSAFEARRAY { USHORT cDims; // # of dimensions // USHORT fFeatures; // flags describing contents // , ULONG cbElements; // # of bytes per element // ULONG cLocks; // used to track memory usage // void* pvData; // actual elements // [size_is(cDims)] SAFEARRAYBOUND rgsabound[] } SAFEARRAY;
IDL SAFEARRAY, .
, , fFeatures:
FADF_AUTO /* array is allocated on the stack */ /* */ FADF_STATIC /* array is statically allocated */ /* */ FADF_EMBEDDEO /* array is embedded in a structure */ /* */ FADF_FIXEDSIZE /* may not be resized or reallocated */ /* */ FADF_BSTR /* an array of BSTRs */ /* BSTR */ FADF_UNKNOWN /* an array of IUnknown* */ /* IUnknown* */ FADF_DISPATCH /* an array of IDispatch* */ /* IDispatch* */ FADF_VARIANT /* an array of VARIANTS */ /* VARIANTS */
SAFEARRAY , IDL , SAFEARRAY, :
HRESULT Method([in] SAFEARRAY(type) *ppsa);
type SAFEARRAY. C++ :
HRESULT Method(SAFEARRAY **psa);
, IDL ; C++ . IDL, SAFEARRAY :
HRESULT Method([in] SAFEARRAY(short) *psa);
Visual Basic :
Sub Method(ByVal psa As Integer())
, Visual Basic . , , Visual Basic .
SAFEARRAY API- , . SAFEARRAY API- :
// get a pointer to the actual array elements // HRESULT SafeArrayAccessData([in] SAFEARRAY *psa, [out] void ** ppv); // release pointer returned by SafeArrayAccessData // , SafeArrayAccessData HRESULT SafeArrayUnaccessData([in] SAFEARRAY *psa); // Get number of dimensions // ULONG SafeArrayGetDim([in] SAFEARRAY *psa); // Get upper bound of a dimension // HRESULT SafeArrayGetUBound([in] SAFEARRAY *psa, [in] UINT nDim, [out] long *pUBound); // Get lower bound of a dimension // HRESULT SafeArrayGetLBound([in] SAFEARRAY *psa, [in] UINT nDim, [out] long *pLBound);
. IDL:
HRESULT Sum([in] SAFEARRAY(long) *ppsa, [out, retval] long *pSum);
SAFEARRAY, (long integers):
STDMETHODIMP MyClass::Sum(SAFEARRAY **ppsa, long *pnSum) { assert(ppsa && *ppsa && pnSum); assert(SafeArrayGetDim(*ppsa) == 1); long iUBound, iLBound; // note that dimension indices are one-based // , HRESULT hr = SafeArrayGetUBound(*ppsa, 1, &iUBound); assert(SUCCEEDED(hr)); hr = SafeArrayGetLBound(*ppsa, 1, &iLBound); assert(SUCCEEDED(hr)); long *prgn = 0; hr = SafeArrayAccessData(*ppsa, (void**)&prgn); *pnSum = 0; for (long i = 0; i < iUBound - iLBound; i++) *pnSum += prgn[i]; SafeArrayUnaccessData(*ppsa); return S_OK; }
, API- , , , .
SAFEARRAY- . SAFEARRAY API- , SAFEARRAY :
SAFEARRAY *SafeArrayCreateVector( [in] VARTYPE vt, // element type // [in] long iLBound, // index of lower bound // [in] unsigned int cElems); // # of elements //
, , , . IDL:
HRESULT GetPrimes([in] long nStart, [in] long nEnd, [out] SAFEARRAY(long) *ppsa);
C++ SAFEARRAY, :
STDMETHODIMP MyClass::GetPrimes (long nMin, long nMax, SAFEARRAY **ppsa) { assert(ppsa); UINT cElems = GetNumberOfPrimes(nMin, nMax); *ppsa = SafeArrayCreateVector(VT_I4, 0, cElems); assert(*ppsa); long *prgn = 0; HRESULT hr = SafeArrayAccessData(*ppsa, (void**)&prgn); assert(SUCCEEDED(hr)); for (UINT i=0; i < cElems; i++) prgn[i] = GetNextPrime(i ? prgn[1 - 1] : nMin); SafeArrayUnaccessData(*ppsa); return S_OK; }
Visual Basic :
Function GetSumOfPrimes(ByVal nMin as Long, ByVal nMax as Long) as Long Dim arr() as Long Dim n as Variant Objref.GetPrimes nMin, nMax, arr GetSumOfPrimes = 0 for each n in arr GetSumOfPrimes = GetSumOfPrimes + n Next n End Function
C++:
long GetSumOfPrimes (long nMin, long nMax) { SAFEARRAY *pArray = 0; HRESULT hr = g_pObjRef->GetPrimes(nMin, nMax, &pArray); assert(SUCCEEDED(hr) && SafeArrayGetDim(pArray) == 1); long *prgn = 0; hr = SafeArrayAccessData(pArray, (void**)&prgn); long iUBound, iLBound, result = 0; SafeArrayGetUBound(pArray, 1, &iUBound); SafeArrayGetLBound(pArray, 1, &iLBound); for (long n = iLBound; n <= iUBound: n++) result += prgn[n]; SafeArrayUnaccessData(pArray); SafeArrayDestroy(pArray); return n; }
, , SAFEARRAY- , [out]- . SafeArrayDestroy , SAFEARRAY.