Changeset 856 for trunk/include/win/wine/obj_base.h
- Timestamp:
- Sep 7, 1999, 7:57:55 PM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/win/wine/obj_base.h
r680 r856 1 /* $Id: obj_base.h,v 1. 9 1999-08-25 11:24:09 sandervlExp $ */1 /* $Id: obj_base.h,v 1.10 1999-09-07 17:54:57 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 */ … … 86 86 return !(guidOne == guidOther); 87 87 } 88 #endif 88 #endif 89 89 90 90 … … 93 93 */ 94 94 /* 95 * The goal of the following set of definitions is to provide a way to use the same 96 * header file definitions to provide both a C interface and a C++ object oriented 97 * interface to COM interfaces. The type of interface is selected automatically 98 * depending on the language but it is always possible to get the C interface in C++ 95 * The goal of the following set of definitions is to provide a way to use the same 96 * header file definitions to provide both a C interface and a C++ object oriented 97 * interface to COM interfaces. The type of interface is selected automatically 98 * depending on the language but it is always possible to get the C interface in C++ 99 99 * by defining CINTERFACE. 100 100 * 101 101 * It is based on the following assumptions: 102 102 * - all COM interfaces derive from IUnknown, this should not be a problem. 103 * - the header file only defines the interface, the actual fields are defined 103 * - the header file only defines the interface, the actual fields are defined 104 104 * separately in the C file implementing the interface. 105 105 * 106 * The natural approach to this problem would be to make sure we get a C++ class and 106 * The natural approach to this problem would be to make sure we get a C++ class and 107 107 * virtual methods in C++ and a structure with a table of pointer to functions in C. 108 * Unfortunately the layout of the virtual table is compiler specific, the layout of 109 * g++ virtual tables is not the same as that of an egcs virtual table which is not the 110 * same as that generated by Visual C+. There are workarounds to make the virtual tables 108 * Unfortunately the layout of the virtual table is compiler specific, the layout of 109 * g++ virtual tables is not the same as that of an egcs virtual table which is not the 110 * same as that generated by Visual C+. There are workarounds to make the virtual tables 111 111 * compatible via padding but unfortunately the one which is imposed to the WINE emulator 112 112 * by the Windows binaries, i.e. the Visual C++ one, is the most compact of all. 113 113 * 114 * So the solution I finally adopted does not use virtual tables. Instead I use inline 114 * So the solution I finally adopted does not use virtual tables. Instead I use inline 115 115 * non virtual methods that dereference the method pointer themselves and perform the call. 116 116 * … … 146 146 * 147 147 * Comments: 148 * - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this' 149 * pointer. Defining this macro here saves us the trouble of having to repeat the interface 150 * name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1 151 * cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not 148 * - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this' 149 * pointer. Defining this macro here saves us the trouble of having to repeat the interface 150 * name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1 151 * cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not 152 152 * 'IDirect3D_VTABLE'. 153 * - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the 153 * - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the 154 154 * inherited methods to form ICOM_IMETHODS. 155 * - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must 156 * be written manually (rather than using a macro to generate the equivalent code) to avoid 155 * - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must 156 * be written manually (rather than using a macro to generate the equivalent code) to avoid 157 157 * macro recursion (which compilers don't like). 158 * - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to 158 * - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to 159 159 * explicitly use the interface name for macro expansion reasons again. 160 * Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's 161 * Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance 160 * Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's 161 * Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance 162 162 * is taken care of by the language. 163 * - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer 164 * method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The 165 * only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and 163 * - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer 164 * method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The 165 * only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and 166 166 * to have it take only the type information (with const if necessary) as parameters. 167 * The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following 168 * macros will not work. This time it's because the ICOM_CALL macro expansion is done only once 169 * the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone 167 * The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following 168 * macros will not work. This time it's because the ICOM_CALL macro expansion is done only once 169 * the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone 170 170 * anyway. 171 * - You may have noticed the double commas after each parameter type. This allows you to put the 172 * name of that parameter which I think is good for documentation. It is not required and since 173 * I did not know what to put there for this example (I could only find doc about IDirect3D2), 171 * - You may have noticed the double commas after each parameter type. This allows you to put the 172 * name of that parameter which I think is good for documentation. It is not required and since 173 * I did not know what to put there for this example (I could only find doc about IDirect3D2), 174 174 * I left them blank. 175 * - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access 176 * to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate 177 * the inherited method definitions there. This time I could have used a trick to use only one 175 * - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access 176 * to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate 177 * the inherited method definitions there. This time I could have used a trick to use only one 178 178 * macro whatever the number of parameters but I prefered to have it work the same way as above. 179 * - You probably have noticed that we don't define the fields we need to actually implement this 180 * interface: reference count, pointer to other resources and miscellaneous fields. That's 181 * because these interfaces are just that: interfaces. They may be implemented more than once, in 182 * different contexts and sometimes not even in Wine. Thus it would not make sense to impose 179 * - You probably have noticed that we don't define the fields we need to actually implement this 180 * interface: reference count, pointer to other resources and miscellaneous fields. That's 181 * because these interfaces are just that: interfaces. They may be implemented more than once, in 182 * different contexts and sometimes not even in Wine. Thus it would not make sense to impose 183 183 * that the interface contains some specific fields. 184 184 * … … 199 199 * HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b); 200 200 * HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b); 201 * }; 201 * }; 202 202 * 203 203 * #ifdef ICOM_CINTERFACE … … 216 216 * 217 217 * Comments: 218 * - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing 219 * the user needs to know to use the interface. Of course the structure we will define to 218 * - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing 219 * the user needs to know to use the interface. Of course the structure we will define to 220 220 * implement this interface will have more fields but the first one will match this pointer. 221 * - The code generated by ICOM_DEFINE defines both the structure representing the interface and 222 * the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to 223 * automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS 221 * - The code generated by ICOM_DEFINE defines both the structure representing the interface and 222 * the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to 223 * automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS 224 224 * to define the IDirect3D methods. 225 * - Each method is declared as a pointer to function field in the jump table. The implementation 226 * will fill this jump table with appropriate values, probably using a static variable, and 225 * - Each method is declared as a pointer to function field in the jump table. The implementation 226 * will fill this jump table with appropriate values, probably using a static variable, and 227 227 * initialize the lpvtbl field to point to this variable. 228 * - The IDirect3D_Xxx macros then just derefence the lpvtbl pointer and use the function pointer 229 * corresponding to the macro name. This emulates the behavior of a virtual table and should be 228 * - The IDirect3D_Xxx macros then just derefence the lpvtbl pointer and use the function pointer 229 * corresponding to the macro name. This emulates the behavior of a virtual table and should be 230 230 * just as fast. 231 * - This C code should be quite compatible with the Windows headers both for code that uses COM 231 * - This C code should be quite compatible with the Windows headers both for code that uses COM 232 232 * interfaces and for code implementing a COM interface. 233 233 * … … 253 253 * public: inline HRESULT FindDevice(LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b) 254 254 * { return ((IDirect3D*)t.lpvtbl)->fnFindDevice(this,a,b); }; 255 * }; 255 * }; 256 256 * 257 257 * Comments: 258 * - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface 259 * definition. The reason for this is to avoid having to duplicate the mehod definitions: once 260 * to have the function pointers in the jump table and once to have the methods in the interface 261 * class. Here one macro can generate both. This means though that the first pointer, t.lpvtbl 262 * defined in IUnknown, must be interpreted as the jump table pointer if we interpret the 263 * structure as the the interface class, and as the function pointer to the QueryInterface 264 * method, t.fnQueryInterface, if we interpret the structure as the jump table. Fortunately this 258 * - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface 259 * definition. The reason for this is to avoid having to duplicate the mehod definitions: once 260 * to have the function pointers in the jump table and once to have the methods in the interface 261 * class. Here one macro can generate both. This means though that the first pointer, t.lpvtbl 262 * defined in IUnknown, must be interpreted as the jump table pointer if we interpret the 263 * structure as the the interface class, and as the function pointer to the QueryInterface 264 * method, t.fnQueryInterface, if we interpret the structure as the jump table. Fortunately this 265 265 * gymnastic is entirely taken care of in the header of IUnknown. 266 * - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions. 267 * - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and 268 * a non-vritual inline method which dereferences it and calls it. This way this method behaves 269 * just like a virtual method but does not create a true C++ virtual table which would break the 270 * structure layout. If you look at the implementation of these methods you'll notice that they 271 * would not work for void functions. We have to return something and fortunately this seems to 266 * - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions. 267 * - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and 268 * a non-vritual inline method which dereferences it and calls it. This way this method behaves 269 * just like a virtual method but does not create a true C++ virtual table which would break the 270 * structure layout. If you look at the implementation of these methods you'll notice that they 271 * would not work for void functions. We have to return something and fortunately this seems to 272 272 * be what all the COM methods do (otherwise we would need another set of macros). 273 * - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter 274 * names and the method invocation using only the formal parameter name. This is the reason why 273 * - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter 274 * names and the method invocation using only the formal parameter name. This is the reason why 275 275 * we need different macros to handle different numbers of parameters. 276 * - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE 276 * - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE 277 277 * macro is defined in which case we would not be here. 278 * - This C++ code works well for code that just uses COM interfaces. But it will not work with 279 * C++ code implement a COM interface. That's because such code assumes the interface methods 278 * - This C++ code works well for code that just uses COM interfaces. But it will not work with 279 * C++ code implement a COM interface. That's because such code assumes the interface methods 280 280 * are declared as virtual C++ methods which is not the case here. 281 281 * … … 312 312 * 313 313 * Comments: 314 * - We first define what the interface really contains. This is th e_IDirect3D structure. The 314 * - We first define what the interface really contains. This is th e_IDirect3D structure. The 315 315 * first field must of course be the virtual table pointer. Everything else is free. 316 * - Then we predeclare our static virtual table variable, we will need its address in some 316 * - Then we predeclare our static virtual table variable, we will need its address in some 317 317 * methods to initialize the virtual table pointer of the returned interface objects. 318 * - Then we implement the interface methods. To match what has been declared in the header file 319 * they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that 318 * - Then we implement the interface methods. To match what has been declared in the header file 319 * they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that 320 320 * we can manipulate the fields. This is performed by the ICOM_THIS macro. 321 321 * - Finally we initialize the virtual table. … … 673 673 ICOM_VTABLE(IUnknown)* lpvtbl; 674 674 #if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE) && !defined(ICOM_CINTERFACE) 675 } __attribute__ ((com_interface)); 675 } __attribute__ ((com_interface)); 676 676 #else 677 677 }; … … 867 867 */ 868 868 #ifdef __WINE__ 869 HRESULT WIN E_StringFromCLSID(const CLSID *id, LPSTR);869 HRESULT WIN32API WINE_StringFromCLSID(const CLSID *id, LPSTR); 870 870 #endif 871 871
Note:
See TracChangeset
for help on using the changeset viewer.