Changeset 184 for trunk/include/win/wine/obj_base.h
- Timestamp:
- Jun 24, 1999, 11:48:07 PM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/win/wine/obj_base.h
r94 r184 1 /* $Id: obj_base.h,v 1. 3 1999-06-10 16:21:52 achimhaExp $ */1 /* $Id: obj_base.h,v 1.4 1999-06-24 21:48:07 phaller Exp $ */ 2 2 /* 3 * This file defines the macros and types necessary to define COM interfaces, 3 * This file defines the macros and types necessary to define COM interfaces, 4 4 * and the three most basic COM interfaces: IUnknown, IMalloc and IClassFactory. 5 5 */ … … 21 21 #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 22 22 const GUID name = \ 23 23 { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 24 24 #else 25 25 #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ … … 28 28 29 29 #define DEFINE_OLEGUID(name, l, w1, w2) \ 30 30 DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46) 31 31 32 32 #define DEFINE_SHLGUID(name, l, w1, w2) DEFINE_OLEGUID(name,l,w1,w2) … … 67 67 return !(guidOne == guidOther); 68 68 } 69 #endif 69 #endif 70 70 71 71 … … 74 74 */ 75 75 /* 76 * The goal of the following set of definitions is to provide a way to use the same 77 * header file definitions to provide both a C interface and a C++ object oriented 78 * interface to COM interfaces. The type of interface is selected automatically 79 * depending on the language but it is always possible to get the C interface in C++ 76 * The goal of the following set of definitions is to provide a way to use the same 77 * header file definitions to provide both a C interface and a C++ object oriented 78 * interface to COM interfaces. The type of interface is selected automatically 79 * depending on the language but it is always possible to get the C interface in C++ 80 80 * by defining CINTERFACE. 81 81 * 82 82 * It is based on the following assumptions: 83 83 * - all COM interfaces derive from IUnknown, this should not be a problem. 84 * - the header file only defines the interface, the actual fields are defined 84 * - the header file only defines the interface, the actual fields are defined 85 85 * separately in the C file implementing the interface. 86 86 * 87 * The natural approach to this problem would be to make sure we get a C++ class and 87 * The natural approach to this problem would be to make sure we get a C++ class and 88 88 * virtual methods in C++ and a structure with a table of pointer to functions in C. 89 * Unfortunately the layout of the virtual table is compiler specific, the layout of 90 * g++ virtual tables is not the same as that of an egcs virtual table which is not the 91 * same as that generated by Visual C+. There are workarounds to make the virtual tables 89 * Unfortunately the layout of the virtual table is compiler specific, the layout of 90 * g++ virtual tables is not the same as that of an egcs virtual table which is not the 91 * same as that generated by Visual C+. There are workarounds to make the virtual tables 92 92 * compatible via padding but unfortunately the one which is imposed to the WINE emulator 93 93 * by the Windows binaries, i.e. the Visual C++ one, is the most compact of all. 94 94 * 95 * So the solution I finally adopted does not use virtual tables. Instead I use inline 95 * So the solution I finally adopted does not use virtual tables. Instead I use inline 96 96 * non virtual methods that dereference the method pointer themselves and perform the call. 97 97 * … … 127 127 * 128 128 * Comments: 129 * - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this' 130 * pointer. Defining this macro here saves us the trouble of having to repeat the interface 131 * name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1 132 * cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not 129 * - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this' 130 * pointer. Defining this macro here saves us the trouble of having to repeat the interface 131 * name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1 132 * cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not 133 133 * 'IDirect3D_VTABLE'. 134 * - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the 134 * - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the 135 135 * inherited methods to form ICOM_IMETHODS. 136 * - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must 137 * be written manually (rather than using a macro to generate the equivalent code) to avoid 136 * - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must 137 * be written manually (rather than using a macro to generate the equivalent code) to avoid 138 138 * macro recursion (which compilers don't like). 139 * - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to 139 * - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to 140 140 * explicitly use the interface name for macro expansion reasons again. 141 * Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's 142 * Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance 141 * Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's 142 * Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance 143 143 * is taken care of by the language. 144 * - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer 145 * method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The 146 * only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and 144 * - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer 145 * method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The 146 * only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and 147 147 * to have it take only the type information (with const if necessary) as parameters. 148 * The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following 149 * macros will not work. This time it's because the ICOM_CALL macro expansion is done only once 150 * the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone 148 * The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following 149 * macros will not work. This time it's because the ICOM_CALL macro expansion is done only once 150 * the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone 151 151 * anyway. 152 * - You may have noticed the double commas after each parameter type. This allows you to put the 153 * name of that parameter which I think is good for documentation. It is not required and since 154 * I did not know what to put there for this example (I could only find doc about IDirect3D2), 152 * - You may have noticed the double commas after each parameter type. This allows you to put the 153 * name of that parameter which I think is good for documentation. It is not required and since 154 * I did not know what to put there for this example (I could only find doc about IDirect3D2), 155 155 * I left them blank. 156 * - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access 157 * to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate 158 * the inherited method definitions there. This time I could have used a trick to use only one 156 * - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access 157 * to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate 158 * the inherited method definitions there. This time I could have used a trick to use only one 159 159 * macro whatever the number of parameters but I prefered to have it work the same way as above. 160 * - You probably have noticed that we don't define the fields we need to actually implement this 161 * interface: reference count, pointer to other resources and miscellaneous fields. That's 162 * because these interfaces are just that: interfaces. They may be implemented more than once, in 163 * different contexts and sometimes not even in Wine. Thus it would not make sense to impose 160 * - You probably have noticed that we don't define the fields we need to actually implement this 161 * interface: reference count, pointer to other resources and miscellaneous fields. That's 162 * because these interfaces are just that: interfaces. They may be implemented more than once, in 163 * different contexts and sometimes not even in Wine. Thus it would not make sense to impose 164 164 * that the interface contains some specific fields. 165 165 * … … 180 180 * HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b); 181 181 * HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b); 182 * }; 182 * }; 183 183 * 184 184 * #ifdef ICOM_CINTERFACE … … 197 197 * 198 198 * Comments: 199 * - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing 200 * the user needs to know to use the interface. Of course the structure we will define to 199 * - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing 200 * the user needs to know to use the interface. Of course the structure we will define to 201 201 * implement this interface will have more fields but the first one will match this pointer. 202 * - The code generated by ICOM_DEFINE defines both the structure representing the interface and 203 * the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to 204 * automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS 202 * - The code generated by ICOM_DEFINE defines both the structure representing the interface and 203 * the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to 204 * automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS 205 205 * to define the IDirect3D methods. 206 * - Each method is declared as a pointer to function field in the jump table. The implementation 207 * will fill this jump table with appropriate values, probably using a static variable, and 206 * - Each method is declared as a pointer to function field in the jump table. The implementation 207 * will fill this jump table with appropriate values, probably using a static variable, and 208 208 * initialize the lpvtbl field to point to this variable. 209 * - The IDirect3D_Xxx macros then just derefence the lpvtbl pointer and use the function pointer 210 * corresponding to the macro name. This emulates the behavior of a virtual table and should be 209 * - The IDirect3D_Xxx macros then just derefence the lpvtbl pointer and use the function pointer 210 * corresponding to the macro name. This emulates the behavior of a virtual table and should be 211 211 * just as fast. 212 * - This C code should be quite compatible with the Windows headers both for code that uses COM 212 * - This C code should be quite compatible with the Windows headers both for code that uses COM 213 213 * interfaces and for code implementing a COM interface. 214 214 * … … 234 234 * public: inline HRESULT FindDevice(LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b) 235 235 * { return ((IDirect3D*)t.lpvtbl)->fnFindDevice(this,a,b); }; 236 * }; 236 * }; 237 237 * 238 238 * Comments: 239 * - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface 240 * definition. The reason for this is to avoid having to duplicate the mehod definitions: once 241 * to have the function pointers in the jump table and once to have the methods in the interface 242 * class. Here one macro can generate both. This means though that the first pointer, t.lpvtbl 243 * defined in IUnknown, must be interpreted as the jump table pointer if we interpret the 244 * structure as the the interface class, and as the function pointer to the QueryInterface 245 * method, t.fnQueryInterface, if we interpret the structure as the jump table. Fortunately this 239 * - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface 240 * definition. The reason for this is to avoid having to duplicate the mehod definitions: once 241 * to have the function pointers in the jump table and once to have the methods in the interface 242 * class. Here one macro can generate both. This means though that the first pointer, t.lpvtbl 243 * defined in IUnknown, must be interpreted as the jump table pointer if we interpret the 244 * structure as the the interface class, and as the function pointer to the QueryInterface 245 * method, t.fnQueryInterface, if we interpret the structure as the jump table. Fortunately this 246 246 * gymnastic is entirely taken care of in the header of IUnknown. 247 * - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions. 248 * - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and 249 * a non-vritual inline method which dereferences it and calls it. This way this method behaves 250 * just like a virtual method but does not create a true C++ virtual table which would break the 251 * structure layout. If you look at the implementation of these methods you'll notice that they 252 * would not work for void functions. We have to return something and fortunately this seems to 247 * - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions. 248 * - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and 249 * a non-vritual inline method which dereferences it and calls it. This way this method behaves 250 * just like a virtual method but does not create a true C++ virtual table which would break the 251 * structure layout. If you look at the implementation of these methods you'll notice that they 252 * would not work for void functions. We have to return something and fortunately this seems to 253 253 * be what all the COM methods do (otherwise we would need another set of macros). 254 * - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter 255 * names and the method invocation using only the formal parameter name. This is the reason why 254 * - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter 255 * names and the method invocation using only the formal parameter name. This is the reason why 256 256 * we need different macros to handle different numbers of parameters. 257 * - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE 257 * - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE 258 258 * macro is defined in which case we would not be here. 259 * - This C++ code works well for code that just uses COM interfaces. But it will not work with 260 * C++ code implement a COM interface. That's because such code assumes the interface methods 259 * - This C++ code works well for code that just uses COM interfaces. But it will not work with 260 * C++ code implement a COM interface. That's because such code assumes the interface methods 261 261 * are declared as virtual C++ methods which is not the case here. 262 262 * … … 293 293 * 294 294 * Comments: 295 * - We first define what the interface really contains. This is th e_IDirect3D structure. The 295 * - We first define what the interface really contains. This is th e_IDirect3D structure. The 296 296 * first field must of course be the virtual table pointer. Everything else is free. 297 * - Then we predeclare our static virtual table variable, we will need its address in some 297 * - Then we predeclare our static virtual table variable, we will need its address in some 298 298 * methods to initialize the virtual table pointer of the returned interface objects. 299 * - Then we implement the interface methods. To match what has been declared in the header file 300 * they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that 299 * - Then we implement the interface methods. To match what has been declared in the header file 300 * they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that 301 301 * we can manipulate the fields. This is performed by the ICOM_THIS macro. 302 302 * - Finally we initialize the virtual table. … … 315 315 316 316 #ifndef ICOM_VIRTUAL_METHODS 317 /* Uses these macros, i.e. do not define ICOM_VIRTUAL_METHODS, if your C++ compiler does not generate 317 /* Uses these macros, i.e. do not define ICOM_VIRTUAL_METHODS, if your C++ compiler does not generate 318 318 * virtual tables with the right layout (i.e. currently most g++ derivatives). 319 319 */ … … 481 481 482 482 #else 483 /* This case can be used if the layout of the virtual tables generated by the C++ 483 /* This case can be used if the layout of the virtual tables generated by the C++ 484 484 * compiler matches that of Visual C++. 485 485 */ … … 775 775 * Predeclare the interfaces 776 776 */ 777 DEFINE_OLEGUID(IID_IClassFactory, 777 DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0); 778 778 typedef struct IClassFactory IClassFactory, *LPCLASSFACTORY; 779 779 780 DEFINE_OLEGUID(IID_IMalloc, 780 DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0); 781 781 typedef struct IMalloc16 IMalloc16,*LPMALLOC16; 782 782 typedef struct IMalloc IMalloc,*LPMALLOC; 783 783 784 DEFINE_OLEGUID(IID_IUnknown, 784 DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0); 785 785 typedef struct IUnknown IUnknown, *LPUNKNOWN; 786 786 … … 992 992 993 993 HRESULT WINAPI CoRevokeClassObject(DWORD dwRegister); 994 HRESULT WINAPI CoRegisterSurrogate(LPSURROGATE pSurrogate); 994 995 995 996 /***************************************************************************** 996 * 997 * COM Server dll - exports 997 998 */ 998 999 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv);
Note:
See TracChangeset
for help on using the changeset viewer.