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