extern(Windows) on XPCOM

Chris Nicholson-Sauls ibisbasenji at gmail.com
Thu Apr 12 22:12:59 PDT 2007


Li Jie wrote:
> I want to call XPCOM and write XPCOM component with D, but I have some problems.
> 
> This is COM object virtual table structure:
> # COM:
> # vtbl -> | a_pointer (I don't know what is this)
> #         | QueryInterface
> # 	| AddRef
> # 	| Release
> 
> And this is XPCOM object virtual table:
> # XPCOM:
> # vtbl -> | QueryInterface
> # 	| AddRef
> # 	| Release
> 
> extern(Windows) only compatible COM, because it added an offset, XPCOM do not need this.
> When call QueryInterface, it really call AddRef.
> And I tried extern(C++) and extern(Pascal), no changes.
> 
> I think that there are 4 solutions:
> 
> 1. Don't use interface, replace with struct, C style:
> # struct nsISupportsVtable  
> # {  
> # extern(Windows) :  
> #     nsresult function (nsISupports*, nsIID* uuid, void** result) QueryInterface;  
> #       
> #     nsrefcnt function(nsISupports*) AddRef;  
> #       
> #     nsrefcnt function(nsISupports*) Release;  
> # }  
> #   
> # struct nsISupports  
> # {  
> #     nsISupportsVtable* vtbl;  
> # }
> 
> Ugly! but it can works.
> 
> 
> 2. Modify XPCOM interface, remove QueryInterface method:
> # extern(Windows)  
> # interface nsISupports  
> # {  
> #     // Remove it from D interface  
> #     // nsresult QueryInterface(nsIID* uuid, void** result);  
> #   
> #     nsrefcnt AddRef();  
> #   
> #     nsrefcnt Release();  
> # }  
> #
> # private  
> # struct VTBL  
> # {  
> #     extern(Windows) nsresult function (nsISupports, nsIID*, void**) QueryInterface;  
> # }  
> #   
> # private  
> # struct ISupports  
> # {  
> #     VTBL* vtbl;  
> # }  
> #   
> # nsresult MyQueryInterface(nsISupports obj, nsIID* iid, void** pout)  
> # {  
> #     ISupports* p = cast(ISupports*)cast(void*)obj;  
> #     return p.vtbl.QueryInterface(obj, iid, pout);  
> # } 
> 
> It can works, replace nsISupports.QueryInterface with MyQueryInterface. But I can't write XPCOM component with D, because no QueryInterface in interface.
> 
> 
> 3. Hack DMD:
> # int InterfaceDeclaration::vtblOffset()
> # {
> #     if (isCOMclass())
> # 	return 0;
> #     return 1;
> # }
> 
> Change to:
> 
> # int InterfaceDeclaration::vtblOffset()
> # {
> #     return 0;
> # }
> 
> And add pointer to IUnknown:
> # extern(Windows)
> # interface IUnknown
> # {
> #     void ___dont__call__me__please_______();
> #     HRESULT QueryInterface(IID* riid, void** pvObject);
> #     ULONG AddRef();
> #     ULONG Release();
> # }
> 
> I don't know whether it can work.
> 
> 4. Hack DMD, add extern(XPCOM), I think it's very difficult to do.
> 
> 
> Any ideas?

I would think a merge of options 3. and 4. would be good.  Ie, add either a second 
interface (IXPUnknown perhaps) or an extern(XPCOM), and modify DMD's 
InterfaceDeclaration::vtblOffset to know about the special case.  It'd be Walter's choice, 
and I'm not so sure XPCOM would be anywhere near the top of his priority list.

*ponder ponder*

-- Chris Nicholson-Sauls


More information about the Digitalmars-d-learn mailing list