Hiya,
In the wined3d code I have, for example, a class surface which inherits a lot of methods of Resource. Most of these methods can be called as-is, and I have code which looks like:
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DResource_GetParent((IWineD3DResource *)iface, pParent); }
Great idea.... but this fails:
IWineD3DResource_GetParent is a macro: #define IWineD3DSurface_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
So we then go iface->lpVtbl->GetTable. Since iface is a surface, once cast to a resource its GetParent is in the same place in the table... Hence the call ends up being effectively
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DSurfaceImpl_GetParent (iface, pParent); }
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
Jason
Ann and Jason Edmeades wrote:
Hiya,
In the wined3d code I have, for example, a class surface which inherits a lot of methods of Resource. Most of these methods can be called as-is, and I have code which looks like:
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DResource_GetParent((IWineD3DResource *)iface, pParent); }
Great idea.... but this fails:
IWineD3DResource_GetParent is a macro: #define IWineD3DSurface_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
So we then go iface->lpVtbl->GetTable. Since iface is a surface, once cast to a resource its GetParent is in the same place in the table... Hence the call ends up being effectively
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DSurfaceImpl_GetParent (iface, pParent); }
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
I don't think I've got enough information to answer you correctly. Is this a multiple inheritance problem? I.e. does the object implement both IWineD3DSurface and IWineD3DResource and not have one directly inheriting from the other?
Rob
On Thursday 13 January 2005 21:43, Robert Shearman wrote:
Ann and Jason Edmeades wrote:
Hiya,
In the wined3d code I have, for example, a class surface which inherits a lot of methods of Resource. Most of these methods can be called as-is, and I have code which looks like:
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DResource_GetParent((IWineD3DResource *)iface, pParent); }
Great idea.... but this fails:
IWineD3DResource_GetParent is a macro: #define IWineD3DSurface_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
So we then go iface->lpVtbl->GetTable. Since iface is a surface, once cast to a resource its GetParent is in the same place in the table... Hence the call ends up being effectively
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DSurfaceImpl_GetParent (iface, pParent); }
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
I don't think I've got enough information to answer you correctly. Is this a multiple inheritance problem? I.e. does the object implement both IWineD3DSurface and IWineD3DResource and not have one directly inheriting from the other?
Rob
Hi
Jason seems to have: - IWineD3DSurface inherits from IWineD3DResource - IWineD3DResource inherits from IUnknown
Jason, why IWineD3DSurface inherits from IWineD3DResource ? as D3DSurfaces dont inherits from Ressources (cf http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/...)
But for me the only (proper) way to handle your problem is to do as done in d3d8 code
Regards, Raphael
Jason seems to have:
- IWineD3DSurface inherits from IWineD3DResource
- IWineD3DResource inherits from IUnknown
Yep...
Jason, why IWineD3DSurface inherits from IWineD3DResource ?
Well wine has
/*************************************************************************** ** * IDirect3DSurface9 interface */ #define INTERFACE IDirect3DSurface9 DECLARE_INTERFACE_(IDirect3DSurface9,IDirect3DResource9) {
and the dxsdk
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/ directx/graphics/reference/d3d/interfaces/idirect3dsurface9/_idirect3dsurfac e9.asp
states
Inherits from IDirect3DResource9
(See the table)
I think the sdk includes also do it this way
Jason
On Thursday 13 January 2005 22:09, you wrote:
Jason seems to have:
- IWineD3DSurface inherits from IWineD3DResource
- IWineD3DResource inherits from IUnknown
Yep...
Jason, why IWineD3DSurface inherits from IWineD3DResource ?
Well wine has
/**************************************************************************
- IDirect3DSurface9 interface
*/ #define INTERFACE IDirect3DSurface9 DECLARE_INTERFACE_(IDirect3DSurface9,IDirect3DResource9) {
and the dxsdk
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c / directx/graphics/reference/d3d/interfaces/idirect3dsurface9/_idirect3dsurfa c e9.asp
states
Inherits from IDirect3DResource9
(See the table)
I think the sdk includes also do it this way
Jason
Well my SDK headers are out-dated :(
Regards, Raphael
I have code which looks like:
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DResource_GetParent((IWineD3DResource *)iface, pParent); }
IWineD3DResource_GetParent is a macro: #define IWineD3DSurface_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
So we then go iface->lpVtbl->GetTable. Since iface is a surface, once cast to a resource its GetParent is in the same place in the table... Hence the call ends up being effectively
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DSurfaceImpl_GetParent (iface, pParent); }
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
I don't think I've got enough information to answer you correctly. Is this a multiple inheritance problem? I.e. does the object implement both IWineD3DSurface and IWineD3DResource and not have one directly inheriting from the other?
No, a single inheritance issue. Let me try to explain...
Resource is defined as having functions A,B,C and its vtbl is {a,b,c} Surface is defined as having functions A,B,C,D,E,F and its vtbl is {a,b,c,d,e,f}. Note 'a' is an entrypoint to surface not resource, since that wasn't possible (see another thread a long time ago!)...
So in surface_A I want to call resource_a, and code it as expected, ie Resource_a((resource) iface, parms)... But the entrypoint, regardless of the casting, is got from the first entry in the vtbl, which (again, regardless of the casting) is surfaces a function...
Better? Jason
Ann and Jason Edmeades wrote:
I have code which looks like:
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DResource_GetParent((IWineD3DResource *)iface, pParent); }
IWineD3DResource_GetParent is a macro: #define IWineD3DSurface_GetParent(p,a) (p)->lpVtbl->GetParent(p,a)
So we then go iface->lpVtbl->GetTable. Since iface is a surface, once cast to a resource its GetParent is in the same place in the table... Hence the call ends up being effectively
HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) { return IWineD3DSurfaceImpl_GetParent (iface, pParent); }
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
I don't think I've got enough information to answer you correctly. Is this a multiple inheritance problem? I.e. does the object implement both IWineD3DSurface and IWineD3DResource and not have one directly inheriting from the other?
No, a single inheritance issue. Let me try to explain...
Resource is defined as having functions A,B,C and its vtbl is {a,b,c} Surface is defined as having functions A,B,C,D,E,F and its vtbl is {a,b,c,d,e,f}. Note 'a' is an entrypoint to surface not resource, since that wasn't possible (see another thread a long time ago!)...
So in surface_A I want to call resource_a, and code it as expected, ie Resource_a((resource) iface, parms)... But the entrypoint, regardless of the casting, is got from the first entry in the vtbl, which (again, regardless of the casting) is surfaces a function...
Better?
In that case, yes, you will have to add a prototype for the base implementation and call it from the inheriting object. You have to tell the compiler where the implementation is somewhere along the line, but putting the base implementation directly into the vtable will result in conflicting types, so adding a new function for the inheriting object is the best way to do it. This would be slightly easier in C++.
Rob
On Thu, 13 Jan 2005 20:33:10 +0000, Ann and Jason Edmeades wrote:
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
I'm kind of confused too but it seems you really want two interfaces that inherit from each other here rather than having two separate interfaces that happen to have the same name.
So, IWineD3DSurface should inherit from IWineD3DResource which in turn should inherit from IUnknown. Then you fill out the vtable appropriately for overrides. Isn't object orientation in C fun :)
typedef struct { IWineD3DSurfaceVtbl *lpVtbl; DWORD refcount; .... } WineD3DSurface;
static IWineD3DSurfaceVtbl SurfaceVtbl = { /* IUnknown methods are reimplemented per object here but you could be cleverer */ WineD3DSurface_QueryInterface, WineD3DSurface_AddRef, WineD3DSurface_Release,
/* Now for the Resource methods */ WineD3DResource_XXX, WineD3DResource_YYY,
/* Now for the Surface methods */ WineD3DSurface_AAA, WineD3DSurface_BBB };
static WineD3DSurface *WineD3DSurface_Create() { WineD3DSurface *obj = HeapAlloc(GetProcessHeap(), 0, sizeof(WineD3DSurface));
obj->lpVtbl = &SurfaceVtbl; }
Of course for object orientation to be *useful* like that, the WineD3DResource methods have to be able to cast the incoming object ptr to a WineD3DResource object, so you need to use struct inheritance like so:
struct WineD3DSurface { WineD3DResource parent; /* note the lack of an asterisk: this embeds a copy of the struct so casting works, not a pointer */
/* add your additional fields here ... now casting a Surface to a Resource works */ }
Remember that lpVtbl can go anywhere :)
thanks -mike
Mike Hearn wrote:
On Thu, 13 Jan 2005 20:33:10 +0000, Ann and Jason Edmeades wrote:
Whats the solution?
In d3d8 I would have coded IWineD3DSurfaceImpl_GetParent as IWineD3DResourceImpl_GetParent(iface, pParent) because the Impl versions were prototyped - Is this the only way to solve this?
I'm kind of confused too but it seems you really want two interfaces that inherit from each other here rather than having two separate interfaces that happen to have the same name.
So, IWineD3DSurface should inherit from IWineD3DResource which in turn should inherit from IUnknown. Then you fill out the vtable appropriately for overrides. Isn't object orientation in C fun :)
typedef struct { IWineD3DSurfaceVtbl *lpVtbl; DWORD refcount; .... } WineD3DSurface;
static IWineD3DSurfaceVtbl SurfaceVtbl = { /* IUnknown methods are reimplemented per object here but you could be cleverer */ WineD3DSurface_QueryInterface, WineD3DSurface_AddRef, WineD3DSurface_Release,
/* Now for the Resource methods */ WineD3DResource_XXX, WineD3DResource_YYY, /* Now for the Surface methods */ WineD3DSurface_AAA, WineD3DSurface_BBB
};
But you'll get a warning because the WineD3DResource functions will take a different type iface variable as their first parameter. You could cast it to the correct type, but you'll lose all type checking on the function and I wouldn't recommend it.
Rob
So, IWineD3DSurface should inherit from IWineD3DResource which in turn should inherit from IUnknown. Then you fill out the vtable appropriately for overrides. Isn't object orientation in C fun :)
typedef struct { IWineD3DSurfaceVtbl *lpVtbl; DWORD refcount; .... } WineD3DSurface;
static IWineD3DSurfaceVtbl SurfaceVtbl = { /* IUnknown methods are reimplemented per object here but you could be
cleverer */
WineD3DSurface_QueryInterface, WineD3DSurface_AddRef, WineD3DSurface_Release, /* Now for the Resource methods */ WineD3DResource_XXX, WineD3DResource_YYY, /* Now for the Surface methods */ WineD3DSurface_AAA, WineD3DSurface_BBB
};
That's what I tried originally, but C cant do it if surface and resource are in different files (That was exactly a thread on wined3d because I hit this and was told there was no way around it).
Also, the Surface XXX may want to override the Resource XXX or it may be happy just calling it...
I'll go for the prototypes/calling directly, as per d3d8 - I've used my editor macro skills to convert the interface definition into prototypes fairly quickly!
And yes... C++ would be a lot easier, and if you knew me you'd know how hard it is saying that (I hate C++ compared to C, Java etc).
Jason
On Thu, 13 Jan 2005 15:21:27 -0600, Robert Shearman wrote:
But you'll get a warning because the WineD3DResource functions will take a different type iface variable as their first parameter. You could cast it to the correct type, but you'll lose all type checking on the function and I wouldn't recommend it.
Hmm, true, how annoying.
Still, I think relaxing type safety in this instance is better than lots of relay functions that just rename the function especially in high performance code like Direct3D.
thanks -mike