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