digitalmars.D - [WinAPI] Problem with an interface...
- Sascha Katzner (20/32) Nov 22 2007 Hi,
- Frits van Bommel (11/23) Nov 22 2007 Interfaces are only compatible with non-D code if they're COM interfaces...
- Sascha Katzner (7/24) Nov 22 2007 But IUnknown itself is declared as an D interface:
- Sascha Katzner (10/32) Nov 22 2007 I've found something...
- Jarrett Billingsley (4/9) Nov 22 2007 IUnknown is "magic", like Object. IUnknown has special significance to ...
-
Stewart Gordon
(9/21)
Nov 22 2007
- Sascha Katzner (6/21) Nov 22 2007 I think extern(Windows) is correct here.
- Sascha Katzner (6/17) Nov 22 2007 It is a little bit inconvenient, because now I have two different kinds
Hi, I'm not sure if this is a bug in the way D handles interfaces or if I misunderstand something. I was trying to translate the Direct3D 10 headers for the Windows API project: http://www.dsource.org/projects/bindings/browser/trunk/win32/directx I have a Windows function (GetTechniqueByName), which returns a pointer to an interface (which in D results to a simple interface, because in D interfaces are allready reference types).ID3D10EffectTechnique GetTechniqueByName(LPCSTR Name); interface ID3D10EffectTechnique { extern(Windows) : BOOL IsValid(); HRESULT GetDesc(D3D10_TECHNIQUE_DESC* pDesc); ID3D10EffectVariable GetAnnotationByIndex(UINT Index); ID3D10EffectVariable GetAnnotationByName(LPCSTR Name); ID3D10EffectPass GetPassByIndex(UINT Index); ID3D10EffectPass GetPassByName(LPCSTR Name); HRESULT ComputeStateBlockMask(D3D10_STATE_BLOCK_MASK* pStateBlockMask); }If I try subsequently to call a function from this interface something very strange happens, the call results in the very next function from the interface declaration being called. For example if I call "technique.IsValid()" D calls GetDesc(), which results in an access violation. This behavior appears only to happen with interfaces which are NOT derived from IUnknown. I have attached a stripped down version of my source attached to this posting and a compiled version with debug info can be found at: http://sascha.katzner.de/misc/interface.exe LLAP, Sascha Katzner
Nov 22 2007
Sascha Katzner wrote:I have a Windows function (GetTechniqueByName), which returns a pointer to an interface (which in D results to a simple interface, because in D interfaces are allready reference types). If I try subsequently to call a function from this interface something very strange happens, the call results in the very next function from the interface declaration being called. For example if I call "technique.IsValid()" D calls GetDesc(), which results in an access violation. This behavior appears only to happen with interfaces which are NOT derived from IUnknown.Interfaces are only compatible with non-D code if they're COM interfaces (i.e. derive from IUnknown). Other interfaces are D(-compiler)-specific and thus incompatible with non-D code. This also means that "interfaces" returned from non-D code that don't derive from IUnknown can't be declared using 'interface'. However, if you know how to call their functions from C you can still use the C-like way to access them (using structs and explicitly accessing the vtable, for example). Non-COM interfaces use a D-specific vtable layout (causing you to call a different function) and calling convention (but you may've gotten "lucky" with two no-argument functions).
Nov 22 2007
Frits van Bommel wrote:Interfaces are only compatible with non-D code if they're COM interfaces (i.e. derive from IUnknown). Other interfaces are D(-compiler)-specific and thus incompatible with non-D code. This also means that "interfaces" returned from non-D code that don't derive from IUnknown can't be declared using 'interface'. However, if you know how to call their functions from C you can still use the C-like way to access them (using structs and explicitly accessing the vtable, for example). Non-COM interfaces use a D-specific vtable layout (causing you to call a different function) and calling convention (but you may've gotten "lucky" with two no-argument functions).But IUnknown itself is declared as an D interface: com.d:interface IUnknown { HRESULT QueryInterface(IID* riid, void** pvObject); ULONG AddRef(); ULONG Release(); }...or is this only some kind of false front, and the real implementation is hidden behind some compiler magic? LLAP, Sascha Katzner
Nov 22 2007
Sascha Katzner wrote:But IUnknown itself is declared as an D interface: com.d:I've found something... internal\object.d:interface IUnknown { HRESULT QueryInterface(IID* riid, void** pvObject); ULONG AddRef(); ULONG Release(); }...or is this only some kind of false front, and the real implementation is hidden behind some compiler magic?/** * Information about an interface. * A pointer to this appears as the first entry in the interface's vtbl[]. */ struct Interface { ClassInfo classinfo; /// .classinfo for this interface (not for containing class) void *[] vtbl; int offset; /// offset to Interface 'this' from Object 'this' }It seems this explains exactly why the next function is called (because D expects an additional first entry which Windows doesn't deliver), when using a normal D interface instead of something derived from IUnknown. What it doesn't explain is, why IUnknown interfaces doesn't have this problem?!? LLAP, Sascha Katzner
Nov 22 2007
"Sascha Katzner" <sorry.no spam.invalid> wrote in message news:fi4el3$1peg$1 digitalmars.com...It seems this explains exactly why the next function is called (because D expects an additional first entry which Windows doesn't deliver), when using a normal D interface instead of something derived from IUnknown. What it doesn't explain is, why IUnknown interfaces doesn't have this problem?!?IUnknown is "magic", like Object. IUnknown has special significance to the compiler; it knows that anything that derives from it is a COM interface.
Nov 22 2007
"Sascha Katzner" <sorry.no spam.invalid> wrote in message news:fi3t6f$1009$1 digitalmars.com...Hi, I'm not sure if this is a bug in the way D handles interfaces or if I misunderstand something. I was trying to translate the Direct3D 10 headers for the Windows API project: http://www.dsource.org/projects/bindings/browser/trunk/win32/directx I have a Windows function (GetTechniqueByName), which returns a pointer to an interface (which in D results to a simple interface, because in D interfaces are allready reference types).<snip> Most of the interface definitions don't have extern(Windows) in them. Are you sure it's right to have it here? Stewart. -- My e-mail address is valid but not my primary mailbox. Please keep replies on the 'group where everybody may benefit.ID3D10EffectTechnique GetTechniqueByName(LPCSTR Name); interface ID3D10EffectTechnique { extern(Windows) :
Nov 22 2007
Stewart Gordon wrote:Most of the interface definitions don't have extern(Windows) in them. Are you sure it's right to have it here?I think extern(Windows) is correct here. BaseTyps.h:#define STDMETHODCALLTYPE __stdcall #define STDMETHOD(method) virtual COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE method #define STDMETHOD_(type,method) virtual COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE methodD3D10effect.h:DECLARE_INTERFACE(ID3D10EffectTechnique) { STDMETHOD_(BOOL, IsValid)(THIS) PURE; STDMETHOD(GetDesc)(THIS_ D3D10_TECHNIQUE_DESC *pDesc) PURE; STDMETHOD_(ID3D10EffectVariable*, GetAnnotationByIndex)(THIS_ UINT Index) PURE; STDMETHOD_(ID3D10EffectVariable*, GetAnnotationByName)(THIS_ LPCSTR Name) PURE; STDMETHOD_(ID3D10EffectPass*, GetPassByIndex)(THIS_ UINT Index) PURE; STDMETHOD_(ID3D10EffectPass*, GetPassByName)(THIS_ LPCSTR Name) PURE; STDMETHOD(ComputeStateBlockMask)(THIS_ D3D10_STATE_BLOCK_MASK *pStateBlockMask) PURE; };LLAP, Sascha Katzner
Nov 22 2007
Since it seems that a D interface is not usable in this case, I've solved this problem like Frits suggested with a struct as vtbl:struct ID3D10EffectTechniqueVtbl { extern(Windows) : BOOL function() IsValid; HRESULT function(D3D10_TECHNIQUE_DESC* pDesc) GetDesc; ID3D10EffectVariable function(UINT Index) GetAnnotationByIndex; ID3D10EffectVariable function(LPCSTR Name) GetAnnotationByName; ID3D10EffectPass function(UINT Index) GetPassByIndex; ID3D10EffectPass function(LPCSTR Name) GetPassByName; HRESULT function(D3D10_STATE_BLOCK_MASK* pStateBlockMask) ComputeStateBlockMask; } alias ID3D10EffectTechniqueVtbl* ID3D10EffectTechnique;It is a little bit inconvenient, because now I have two different kinds of "interfaces", but it works. ;-) Thanks all, Sascha Katzner
Nov 22 2007