, , . . IDL:
HRESULT f([out] short *ps);
:
short s; HRESULT hr = p->f(&s); // s now contains whatever f wrote // s , f
, . ( ) , :
short *ps; // the function says it takes a short *, so ... // , * short, ... HRESULT hr = p->f(ps);
:
STDMETHODIMP MyClass::f(short *ps) { static short n = 0; *ps = n++; return S_OK; }
, . , , ( , " ", auto ), , . , [out], , .
, , . IDL- :
typedef struct tagPoint { short x; short ; } Point; HRESULT g([out] Point *pPoint);
, : , :
Point pt; HRESULT hr = p->g(&pt);
:
Point *ppt; // random unitialized pointer // HRESULT hr = p->g(ppt); // where should proxy copy x & to? // x ?
, ( ) x y.
, . IDL:
[uuid(E02E5345-l473-11d1-8C85-0080C73925BA),object ] interface IDogManager : IUnknown { typedef struct tagHUMAN { long nHumanID; } HUMAN; typedef struct tagDOG { long nDogID; [unique] HUMAN *pOwner; } DOG; HRESULT GetFromPound([out] DOG *pDog); HRESULT TakeToGroomer([in] const DOG *pDog); HRESULT SendToVet([in, out] DOG *pDog); }
, , . , :
DOG fido; // argument is a DOG *, so caller needs a DOG // DOG *, DOG HUMAN dummy; // the DOG refers to an owner, so alloc space? // DOG , ? fido.pOwner = &dummy; HRESULT hr = p->GetFromPound(&fido); // is this correct? // ?
, DOG, . . , , DOG. .
, , . , , (top-level). , , (embedded) . GetFromPound pDog . pDog->pOwner . , DOG [unique] pOwner. , [pointer_default]:
[ uuid(E02E5345-1473-11d1-8C85-0080C73925BA), object, pointer_default(ref) // default embedded ptrs to [ref] // [ref] ] interface IUseStructs : IUnknown { typedef struct tagNODE { long val; [unique] struct tagNODE *pNode; // explicitly [unique] // [unique] } NODE; typedef struct tagFOO { long val; long *pVal; // implicitly [ref] // [ref] } FOO; HRESULT Method([in] FOO *pFoo, [in, unique] NODE *pHead); }
[pointer_default] , . , , pVal FOO. pNode NODE , [pointer_default] . pFoo pHead [pointer_default] , [ref], ( pHead).
, , , . [in] , , :
HUMAN bob = { 2231 }; DOG fido = { 12288, &bob }; // fido is owned by bob // fido bob'y HRESULT hr = p->TakeToGroomer(&fido); // this is correct! // !
, [out] [in,out]. , [out] [in,out], , , , [in]. , [out] [in, out], ( ). , . , :
typedef struct tagNODE { short value; [unique] struct tagNODE *pNext; } NODE:
, . , ( ) , .
, , , , , ? (task allocator) - . , , [out] [in,out]. - API- :
void *CoTaskMemAlloc(DWORD cb); // allocate cb bytes // cb void CoTaskMemFree(void *pv); // deallocate memory at *pv // *pv void *CoTaskMemRealloc(void *pv,DWORD cb); // grow/shrink *pv // / *pv
, : malloc, free realloc. , [out] [in,out]. , . , . , , , , DLL.
, , , GetFromPound:
HRESULT GetFromPound([out] DOG *pDog);
DOG (pDog ), HUMAN (pDog->pOwner [out]- ). :
STDMETHODIMP GetFromPound(/*[out]*/DOG *pDog) { short did = LookupNewDogId(); short hid = LookupHumanId(did); pDog->nDogID = did; // allocate memory for embedded pointer // pDog->pOwner = (HUMAN*) CoTaskMemAlloc(sizeof(HUMAN)); if (pDog->pOwner == 0) // not enough memory // return R_OUTOFMEMORY; pDog->pOwner->nHumanID = hid; return S_OK; }
, HRESULT E_OUTOFMEMORY, , - .
, GetFromPound, , , :
DOG fido; HRESULT hr = p->GetFromPound(&fido); if (SUCCEEDED(hr)) { printf("The dog %h is owned by %h", fido.nDogID, fido.pOwner->nHumanID); // data has been consumed, so free the memory // , CoTaskMemFree(fido.pOwner); }
, , .
[out]- . [in, out]- . [in, out]- . , , CoTaskMemRealloc. , , CoTaskMemRealloc ( , ). , , , . IDL:
HRESULT SendToVet([in, out] DOG *pDog);
HUMAN, . :
HUMAN *pHuman = (HUMAN*)CoTaskMemAllocc(sizeof(HUMAN)); pHuman->nHumanID = 1522; DOG fido = { 4111, pHuman }; HRESULT hr = p->SendToVet(&fido); // [in, out] if (SUCCEEDED(hr)) { if (fido.pOwner) printf("Dog is now owned by %h", fido.pOwner->nHumanID); CoTaskMemFree(fido.pOwner); // OK to free null ptr. // }
, , , :
STDMETHODIMP MyClass::SendToVet(/*[in, out]*/DOG *pDog) { if (fido.pOwner == 0) fido.pOwner = (HUMAN*)CoTaskMemAlloc(sizeof (HUMAN)); if (fido.pOwner == 0) // alloc failed // return E_OUTOFMEMORY; fido.pOwner->nHumanID = 22; return S_OK; }
[in,out]- , .
- . Windows NT IMall :
[ uuid(00000002-0000-0000-C000-000000000046),local,object] interface IMalloc : IUnknown { void *Alloc([in] ULONG cb); void *Realloc ([in, unique] void *pv, [in] ULONG cb); void Free([in, unique] void *pv); ULONG GetSize([in, unique] void *pv); int DidAlloc([in, unique] void *pv); void HeapMinimize(void); }
IMalloc API- CoGetMalloc:
HRESULT CoGetMalloc( [in] DWORD dwMemCtx, // reserved, must be one // , [out] IMalloc **ppMalloc); // put it here! // !
, CoTaskMemAlloc:
HUMAN *pHuman = (HUMAN*)CoTaskMemAlloc(sizeof(HUMAN));
:
IMalloc *pMalloc = 0; pHuman = 0; HRESULT hr = CoGetMalloc(1, &pMalloc); if (SUCCEEDED(hr)) { pHuman = (HUMAN*)pMalloc->Alloc(sizeof(HUMAN)); pMalloc->Release(); }
, , Windows NT, . CoTaskMemAlloc , .
, , . , , . . - . , , . , [out]- [in, out]- ORPC- . . 7.1, ( ) CoTaskMemFree , . , . ORPC- CoTaskMemAlloc , .
CoTaskMemFree, , , .
, ( ). (spy object), . , , IMallocSpy:
[ uuid(0000001d-0000-0000-C000-000000000046),local,object ] interface IMallocSpy : IUnknown { ULONG PreAlloc([in] ULONG cbRequest); void *PostAlloc([in] void *pActual); void *PreFree([in] void *pRequest,[in] BOOL fSpyed); void PostFree([in] BOOL fSpyed); ULONG PreRealloc([in] void *pRequest,[in] ULONG cbRequest, [out] void **ppNewRequest,[in] BOOL fSpyed); void *PostRealloc([in] void *pActual, [in] BOOL fSpyed); void *PreGetSize([in] void *pRequest, [in] BOOL fSpyed); ULONG PostGetSize([in] ULONG cbActual,[in] BOOL fSpyed); void *PreDidAlloc([in] void *pRequest, [in] BOOL fSpyed); int PostDidAlloc([in] void *pRequest, [in] BOOL fSpyed, [in] int fActual); void PreHeapMinimize(void); void PostHeapMinimize(void); }
, IMalloc IMallocSpy : , , , , , . " " (premethod) , . " " (postmethod) , . , . API- (Malloc spy) :
HRESULT CoRegisterMallocSpy([in] IMallocSpy *pms);
(CoRegisterMallocSpy CO_E_OBJISREG , ). API- CoRevokeMallocSpy:
HRESULT CoRevokeMallocSpy(void);
, , .