£16.995
FREE Shipping

Essential COM

Essential COM

RRP: £33.99
Price: £16.995
£16.995 FREE Shipping

In stock

We accept the following payment methods

Description

const HRESULT CALC_E_IAMHOSED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, Ox200 + 15); The convention for user-defined HRESULTs is to select information code values above Ox200 to avoid reusing values already used by system HRESULTs. Although not crucial, this avoids overloading values that already have meaning for standard interfaces. For example, most HRESULTs have text-based human-readable descriptions that can be resolved at runtime using the FormatMessage API function. By selecting HRESULTs that do not collide with system-defined values, there is no chance that an erroneous error message may be found. To allow methods to return a logical result that is not related to the method's physical HRESULT, COM IDL supports the retval parameter attribute. The retva1 attribute indicates that the associated physical method parameter is actually the logical result of the operation and, in environments that support this, the parameter should be mapped as the result of the operation. Given the following IDL method definition: void *FastString::Dynamic_Cast(const char *pszType) { void *pvResult = 0; if (strcmp(pszType, "IFastString") == 0) pvResult = static_cast (this); else if (strcmp(pszType, "IPersistentObject") == 0) pvResult = static_cast (this); else if (strcmp(pszType, "IExtensibleObject") == 0) pvResult = static_cast (this); else return 0; II request for unsupported interface II pvResult now contains a duplicated pointer, so II we must call DuplicatePointer prior to returning ((IExtensibleObject*)pvResult)->DuplicatePointer(); return pvResult; } they continue to work properly. The problem arises when new clients that expect IFastStri ng to have four methods happen to use older objects that do not implement this method. When the client calls the Fi ndN method on an object compiled against the original interface definition, the results are very well defined. The program crashes. The problem with this technique is that it breaks the encapsulation of the object by modifying the public interface. Just as changing the public interface to a C++ class can cause compile-time errors when the client code is rebuilt, changing the binary interface definition will cause runtime errors when the client code is reexecuted. This implies that interfaces must be immutable and cannot change once published. The solution to this problem is to allow an implementation class to expose more than one interface. This can be achieved either by designing an interface to derive from another related interface or by allowing an implementation class to inherit from several unrelated interface classes. In either case, the client could use C++'s Runtime Type Identification (RTTI) feature to interrogate the object at runtime to ensure that the requested functionality is indeed supported by the object currently in use. Consider the simple case of an interface extending another interface. To add a Fi ndN operation to IFastStri ng that allows finding the nth occurrence of a substring, one would derive a second interface from IFastStr.i ng and add the new method definition there: mats the resultant GUID into one of four formats suitable for inclusion in IDL or C++ source code. When working in IDL, the fourth format (the canonical text form) is what is needed. To associate the physical name of the interface with its definition in IDL, the second nonoptional interface attribute, [uui d], is used. The [uui d] attribute accepts one parameter, the canonical textual form of the GUID:

Essential COM - PDF Free Download Essential COM - PDF Free Download

ride each of the pure virtual functions with meaningful implementations. This inheritance relationship will result in objects that have an object layout that is a binary superset of the layout of the interface class (which ultimately is just a vptr/vtbl). This is because the "is-a" relationship between derived and base class applies at the binary level in C++ just as it applies at the modeling level in object-oriented design: shaped much of the mindset of the C++ community at large. One of the principal goals for C++ was to allow programmers to build user-defined types (UDTs) that could be reused outside their original implementation context. This principle underpins the idea of class libraries or frameworks as we know them today. Since the introduction of C++, a marketplace for C++ class libraries emerged, albeit rather slowly. One reason that this marketplace has not grown as fast as one might expect is related to the define BASE_OFFSET(ClassName, BaseName) \ (DWORD(static_cast (reinterpret_cast\ (OxlOOOOOOO))) - OxlOOOOOOO) #define BEGIN_INTERFACE_TABLE(ClassName) \ typedef ClassName _IT(ls;\ canst INTERFACE_ENTRY *GetlnterfaceTable(void) {\ static const INTERFACE_ENTRY table[] = {\ #define IMPLEMENTS_INTERFACE(Itf) \ {&IID_##Itf,ENTRY_IS_OFFSET,BASE_OFFSET(_ITCls,Itf)}, #define IMPLEMENTS_INTERFACE-AS(req, Itf) \ {&IID_##req,ENTRY_IS_OFFSET,BASE_OFFSET(_ITCls,Itf)}, FACILITY_ITF is used by interface-specific HRESULTs and is also the only legal facility code for user-defined HRESULTs. FACILITY_ITF values need only be unique in the context of a particular interface. The standard headers define the MAKE_HRESULT macro for composing user-defined HRESULTs from the three required fields:place was to call del ete thi s, it is legal to optimize away the reference count for non-heap-based objects: As previously described, clients call Querylnterface providing the object with a pointer to an interface pointer as the second parameter together with an lID that identifies the type of interface pointer that is expected: IPug *pPug = 0; hr = punk->QueryInterface(IID_IPug, (void**)&pPug); Unfortunately, the following looks equally correct to the C++ compiler: IPug *pPug = 0; hr = punk->QueryInterface(IID_ICat, (void**)&pPug); This more subtle variation also compiles correctly: IPug *pPug = 0; hr = punk->QueryInterface(IID_IPug, (void**)pPug); Given that the rules of inheritance do not apply to pointers, this alternative definition of QueryInterface does not alleviate the problem: HRESULT QueryInterface(REFIID riid, IUnknown** ppv); as implicit upcasting applies only to instances and pointers to instances, not pointers to pointers to instances: IDe ri ved *~'rppd; IBase **ppb = ppd; II illegal This same limitation applies to references to pointers as well. The following alternative definition is arguably more convenient for clients to use: HRESULT QueryInterface(const IID& riid, void* ppv); as it allows clients to forgo the cast. Unfortunately, this solution does not reduce the number of errors (both of the preceding errors are still possible) and, by eliminating the need for a cast, removes a visual indicator that C++ type safety might be in jeopardy. Given the desired semantics of QueryInterface, the argument types Microsoft chose are reasonable, if not type safe or elegant. The simplest way to avoid QueryInterface-related errors is to always be certain that the lID matches the type of the interface pointer that is passed as the second parameter to QueryInterface. In effect, the first parameter to requires all persistent objects to support the Length and Find operations as well. For some very small subset of objects, this might make sense. However, to make the IPers; stentObject interface as generic as possible, it should really be its own interface and not derive from IFastStri ng: class IPersistentObject { public: virtual void Delete(void) = 0; virtual bool Load(const char *pszFileName) virtual bool Save(const char *pszFileName)

Essential Communications Executive Coaching Los Angeles - Essential Communications

object, uuid(DF12E155-A29A-lldO-8C2D-0080C73925BA)] interface IOldPug : IPug { HRESULT SnoreLoudly(void); }

Resource Management One remaining problem with supporting multiple interfaces from a single object becomes clear when examining the client usage pattern of the Dynami c_Cast method. Consider the following client code: void f(void) { IFastString *pfs = 0; IPersistentObject *ppo = 0; pfs = CreateFastString("Feed BOB"); if (pfs) { ppo = (lPersistentObject *) pfs->Dynami c_Cast("IPersi stentObject"); if (! ppo) pfs->Delete(); else { ppo->Save(IC:\\autoexec.bat"); ppo->Delete(); } } } Because FastStri ng derives from IFastStri ng, the binary layout of FastStri ng objects must be a superset of the binary layout of IFastStri ng. This means that FastStri ng objects will contain a vptr that points to an IFastStri ngcompatible vtbl. Since FastStri ng is a concrete instantiable data type, its vtbl will contain pointers to actual implementations of the Length and Fi nd methods. This relationship is illustrated in Figure 1.6. Even though the public operations of the data type have been hoisted to become pure virtual functions in an interface class, the client cannot instantiate FastStri ng objects without having the class definition of the implementation class. Revealing the implementation class definition to the client would bypass the binary encapsulation of the interface, which would defeat the purpose of using an interface class. One reasonable technique for allowing clients to instantiate FastStri ng objects would be to export a global function from the ifaststring.h /////////// class IFastString { public: virtual void Delete(void) = 0; virtual int Length(void) const = 0; virtual int Find(const char *psz) const class IExtensibleObject { public: virtual void *Dynamic_Cast(const char* pszType) =0; virtual void Delete(void) = 0; } ; The [1 oca1] attribute suppresses the generation of networking code for this interface. This attribute is necessary to relax COM's requirement that all remotable methods must return HRESULTs. As discussed in later chapters, IUnknown is treated specially when dealing with remote objects. Note that the actual IDL interface definitions found in the SDK headers will vary slightly from the definitions found in this text. The actual definitions often contain additional attributes to optimize the generated networking code that are not relevant to the discussion at hand. When in doubt, consult the latest version of the SDK header files for the complete definition. IUnknown is the root of all COM interfaces. IUnknown is the only COM interface that does not derive from another COM interface. Every other legal COM interface must derive from IUnknown directly or from one other legal COM interface, which itself must derive either from IUnknown directly or from one other legal COM interface. This means that at the binary level all COM interfaces are pointers to vtbls that begin with the three entries Que rylnte rface, AddRef, and Release. Any interface-specific methods will have vtbl entries that appear after these common three entries. To derive from an interface in IDL, either define the base interface in the same IDL file or use the import directive to make the external IDL definition of the base interface visible in the current scope:

ESSENTIALS - 原创潮牌ESSENTIALS网上商城 ESSENTIALS - 原创潮牌ESSENTIALS网上商城

Simplicity Leads to Malleability mal·le·a·ble (mal'e-e-bel) adjective 1. Capable of being shaped or formed, as by hammering or pressure: a malleable metal. 2. Easily controlled or influenced; tractable. 3. Able to adjust to changing circumstances; adaptable: the malleable mind of the pragmatist. 3 if (riid == IID_IUnknown) *ppv = static_cast (this); Either of these two code fragments is legal for the implementation of PugCat. The former version is preferred, as many compilers produce slightly more efficient code when the leftmost base class is used. 4

Bedroom

The unexpected behavior stems from the fact that the destructor for the interface class is not virtual. This means that the call to the delete operator will not dynamically find the mDst derived destructor and recursively destroy the object from the outermost type to the base type. Because the FastStri ng destructor is never called, the preceding example leaks the buffer memory used to hold the string "Deface me". One obvious solution to this problem is to make the destructor virtual in the interface class. Unfortunately, this pollutes the compiler independence of class IExtensibleObject { public: virtual void *Dynamic_Cast(const char* pszType) virtual void DuplicatePointer(void) = 0; virtual void DestroyPointer(void) = 0; all compilers on a given platform must produce equivalent machine code sequences for the following client code fragment:

Essential Education Student Login Essential Education Student Login

The first parameter (ri i d) is the physical name of the interface being requested. The second parameter (ppv) points to an interface pointer variable that on successful completion will contain the requested interface pointer. In response to a Querylnterface request, if the object does not support the requested interface type, it must return E_NOINTERFACE after setting *ppv to null. If the object does support the requested interface, it must overwrite *ppv with a pointer of the requested type and return the HRESULT S_OK. Because ppv is an [out] parameter, the implementation of Querylnterface must AddRef the resultant pointer prior to returning control to the caller (see guideline A2 from earlier in this chapter). This AddRef call must be matched by a Re1ease call from the client. The following shows runtime type discovery using C++'s dynami c_cast operator based on the Dog/Cat type hierarchy described earlier in this chapter:class IPersistentObject { public: virtual void *Dynamic_Cast(const char *pszType) =0; virtual void Delete(void) = 0; virtual bool Load(const char *pszFileName) 0; virtual bool Save(const char *pszFileName) 0; } ; Optimizing Querylnterface The de facto implementation of Querylnterface shown earlier in this chapter is fairly straightforward and easily maintained by anyone who has a basic understanding of COM and C++. However, many production environments and frameworks favor a data-driven implementation to achieve greater extensibility and better performance due to code size reduction. Such implementations assume that each COM-compliant class provides a table that maps each supported lID onto some aspect of the object using fixed offsets or some other technique. In essence, the implementation of Querylnterface shown earlier in this chapter builds a table based on the compiled machine code for each sequential if statement and the fixed offsets are calculated using the stati c_cast operator (stat; c_cast simply adds the offset of the base class to find the typecompatible vptr). To implement a table-driven Querylnterface, one first needs to define what the table will contain. At a minimum, each table entry will need to contain a pointer to an lID and some additional state that allows the implementation to find the object's vptr for the requested interface. For maximum flexibility, storing a function pointer at each table entry would support the Figure 2.2 HRESULTs As shown in Figure 2.2, HRESULTs are partitioned into three bit-fields: the severity bit, the facility code, and the information code. The severity bit indicates whether the operation succeeded or not, the facility code indicates what technology the HRESULT corresponds to, and the information code is the precise result within the specified technology and severity. The SDK headers define two macros that simplify coding with .HRESULTs:



  • Fruugo ID: 258392218-563234582
  • EAN: 764486781913
  • Sold by: Fruugo

Delivery & Returns

Fruugo

Address: UK
All products: Visit Fruugo Shop