extern(Windows) on XPCOM

Li Jie cpunion at gmail.com
Thu Apr 12 21:49:34 PDT 2007


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?


More information about the Digitalmars-d-learn mailing list