Thread overview | |||||
---|---|---|---|---|---|
|
April 13, 2007 extern(Windows) on XPCOM | ||||
---|---|---|---|---|
| ||||
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? |
April 13, 2007 Re: extern(Windows) on XPCOM | ||||
---|---|---|---|---|
| ||||
Posted in reply to Li Jie | 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 |
April 21, 2007 Re: extern(Windows) on XPCOM | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | 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. |
Copyright © 1999-2021 by the D Language Foundation