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