extern(Windows) on XPCOM
Li Jie
cpunion at gmail.com
Sat Apr 21 05:56:54 PDT 2007
Chris Nicholson-Sauls дµ½:
>
> 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.
My friend, h_rain has found a simple way, rename nsISupports to IUnknown, like this:
---------------------------------------
extern(Windows)
interface IUnknown {
// some methods
}
alias IUnknown nsISupports;
extern(Windows)
interface nsIFile : nsISupports {
// some methods
}
---------------------------------------
It works fine, and it is beautiful.
More information about the Digitalmars-d-learn
mailing list