Bug 12607 – Document that IUnknown classes must mark toString with extern(D) when overriding it

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dlang.org
Product
D
Version
D2
Platform
All
OS
Windows
Creation time
2014-04-21T14:40:00Z
Last change time
2014-04-21T22:16:27Z
Assigned to
andrej.mitrovich
Creator
andrej.mitrovich

Comments

Comment #0 by andrej.mitrovich — 2014-04-21T14:40:36Z
Test 1: ----- import core.sys.windows.windows; import std.c.windows.com; class C : IUnknown { string toString() { return "E"; } extern(Windows) HRESULT QueryInterface(const(IID)*, void**) { return typeof(return).init; } extern(Windows) uint AddRef() { return 0; } extern(Windows) uint Release() { return 0; } } void main() { } ----- $ dmd test.d > Deprecation: class test.C use of object.Object.toString() hidden by C is deprecated. Use 'alias Object.toString toString;' to introduce base class overload set. Test 2: ----- import core.sys.windows.windows; import std.c.windows.com; class C : IUnknown { override string toString() { return "E"; } extern(Windows) HRESULT QueryInterface(const(IID)*, void**) { return typeof(return).init; } extern(Windows) uint AddRef() { return 0; } extern(Windows) uint Release() { return 0; } } void main() { } ----- $ dmd test.d > Error: function test.C.toString does not override any function, did you mean to override 'object.Object.toString'?
Comment #1 by schveiguy — 2014-04-21T14:49:10Z
I JUST was playing around with this. I think an IUnknown class is implicitly extern(Windows) for all the methods. You have to explicitly mark toString as extern(D).
Comment #2 by andrej.mitrovich — 2014-04-21T14:52:46Z
(In reply to Steven Schveighoffer from comment #1) > I JUST was playing around with this. > > I think an IUnknown class is implicitly extern(Windows) for all the methods. Ah, thanks. I kept seeing people use "extern(Windows):" in their COM classes and thought that was strange. I'll update this so it becomes a documentation issue.
Comment #3 by andrej.mitrovich — 2014-04-21T14:57:51Z
The only problem is, how do you call toString via an IUnknown interface? I need it to implement better support for formatting COM objects, see Issue 11175. IUnknown doesn't declare toString, but if you cast an IUnknown interface to object you get back null.
Comment #4 by schveiguy — 2014-04-21T15:03:51Z
(In reply to Andrej Mitrovic from comment #3) > The only problem is, how do you call toString via an IUnknown interface? You can't. Because the layout of IUnknown interfaces MUST follow COM, the RTTI link to D's typeinfo system is missing. Remember that a proper D interface has a mechanism of defining how to find the object start (and therefore the vtable). An IUnknown interface does not have that. Note that an IUnknown object may not even be a D object! Once you go into IUnknown land, there's no coming back out (bwahahaha!)
Comment #5 by andrej.mitrovich — 2014-04-21T15:12:14Z
(In reply to Steven Schveighoffer from comment #4) > Once you go into IUnknown land, there's no coming back out (bwahahaha!) And somewhat ironically the spec defines IUnknown as using the extern(System) calling convention, rather than saying it's extern(Windows), as if non-Windows systems will ever support COM.
Comment #6 by github-bugzilla — 2014-04-21T22:16:27Z
Commits pushed to master at https://github.com/D-Programming-Language/dlang.org https://github.com/D-Programming-Language/dlang.org/commit/1bf4ff048ac36104a713f3b467cf6f5426f3a4c9 Fix Issue 12607 - Document that IUnknown classes must mark toString with extern(D) when overriding it. https://github.com/D-Programming-Language/dlang.org/commit/652b96b865f5378c166b553b45ac6786d3e3c37e Merge pull request #543 from AndrejMitrovic/Fix12607 Issue 12607 - Document that IUnknown classes must mark toString with extern(D) when overriding it