digitalmars.D - pragma(mangle) on types
- Jacob Carlborg (31/31) Jul 11 2017 In D it's possible to use pragma(mangle) on a function to set the name
- Steven Schveighoffer (4/10) Jul 11 2017 [snip]
- Moritz Maxeiner (59/66) Jul 11 2017 We definitely need to address this, as the obvious workaround is
- Moritz Maxeiner (8/22) Jul 11 2017 Thinking about this a bit more it might make sense to introduce
- Jacob Carlborg (5/11) Jul 11 2017 Yeah, that makes sense. I didn't really think about that the C++ mangler...
In D it's possible to use pragma(mangle) on a function to set the name that will actually end up in the binary. This is useful if you need to link to a C function that uses the same name as a keyword in D. I think we need the same thing for types as well. This is important when binding to C++ and Objective-C. For C++ it's due the the types are mangled as part of function signatures. Other than conflicting D keywords, it's also important for another reason. In C, the name of structs live in their own namespace, making it possible to have a struct and a function with the same name. Since you always need to use "struct <name>" in C when referring to the type it works. This caused a problem [1]. There's a function called "stat", which also accepts an argument of the type "stat". In D, the struct is declared "stat_t" to avoid the conflict with the function. When using C functions this works perfectly fine since no mangling is used. But when using a C++ function taking an argument of the type "stat_t" this will generate the wrong mangling since it's expected to be "stat" on the C++ side. For Objective-C a similar scenario can occur. Because in Objective-C protocols (what we call interfaces in D) and classes live in different namespaces. In Objective-C there's a root class called "Object" just as in D. But in Objective-C this class also conforms to a protocol called "Object". For this to work properly from the D side, one needs to be renamed in the D code and use pragma(mangle) to set the actual name that would end up in the binary. I suggest that we add support for using pragma(mangle) on types as well. Thoughts? I have already implemented the support for Objective-C classes in an old branch several years ago. [1] https://issues.dlang.org/show_bug.cgi?id=16650 -- /Jacob Carlborg
Jul 11 2017
On 7/11/17 3:28 AM, Jacob Carlborg wrote:In D it's possible to use pragma(mangle) on a function to set the name that will actually end up in the binary. This is useful if you need to link to a C function that uses the same name as a keyword in D. I think we need the same thing for types as well. This is important when binding to C++ and Objective-C.[snip] All sounds good to me. -Steve
Jul 11 2017
On Tuesday, 11 July 2017 at 07:28:59 UTC, Jacob Carlborg wrote:In D it's possible to use pragma(mangle) on a function to set the name that will actually end up in the binary. This is useful if you need to link to a C function that uses the same name as a keyword in D. I think we need the same thing for types as well. This is important when binding to C++ and Objective-C. [...]We definitely need to address this, as the obvious workaround is atrocious: --- // Struct as declared when interfacing with C struct IntC { int i; } // Wrapping struct (matching the name declared in C++) to be used for C++ function stubs struct IntCC { IntC v; } extern(C++) void foo(IntCC integer); // D wrapper calling into the stubs void foo(IntC integer) { foo(IntCC(integer)); } --- I think type pragmas would be a reasonable addition, but I'm as of yet not convinced they will actually help much in this case, because they define what the final symbol name will be in object code and in C++ the symbol mangling is left up to the compiler [1]. If you wrote code like this: --- pragma(mangle, "Int") struct IntC { int i; } extern(C++) void foo(IntC integer); --- you would be stating that the mangled symbol of "IntC" in the object code generated for C++ shall be "Int". This may usually be the case, but AFAIK there's no guarantee that your C++ compiler will do so. In the workaround shown above things "work" because we are merely specifying the symbols (unmangled) name and letting the D compiler worry about choosing the appropriate C++ mangling, but with pragma(mangle) we would then have to litter the declaration with C++ mangling schemes, i.e. --- version (CCManglingSchemeA) { pragma(mangle, "ManglingAInt"); struct IntC {...} } else version (CCManglingSchemeB) { pragma(mangle, "ManglingBInt"); struct IntC {...} } --- Manually matching C++ mangling schemes doesn't strike me as the best option, but I also don't know how to do it better (other than the workaround above). [1] https://en.wikipedia.org/wiki/Name_mangling#Standardised_name_mangling_in_C.2B.2B
Jul 11 2017
On Tuesday, 11 July 2017 at 13:14:39 UTC, Moritz Maxeiner wrote:On Tuesday, 11 July 2017 at 07:28:59 UTC, Jacob Carlborg wrote:Thinking about this a bit more it might make sense to introduce another pragma, e.g. `pragma(name, "...")`, which would essentially mean "the identifier used in the declaration this pragma applies to is chosen for identifier restrictions in D; use the identifier specified by the pragma as the starting point for mangling instead",In D it's possible to use pragma(mangle) on a function to set the name that will actually end up in the binary. This is useful if you need to link to a C function that uses the same name as a keyword in D. I think we need the same thing for types as well. This is important when binding to C++ and Objective-C. [...][...] Manually matching C++ mangling schemes doesn't strike me as the best option, but I also don't know how to do it better (other than the workaround above).
Jul 11 2017
On 2017-07-11 15:25, Moritz Maxeiner wrote:Thinking about this a bit more it might make sense to introduce another pragma, e.g. `pragma(name, "...")`, which would essentially mean "the identifier used in the declaration this pragma applies to is chosen for identifier restrictions in D; use the identifier specified by the pragma as the starting point for mangling instead",Yeah, that makes sense. I didn't really think about that the C++ mangler might use something slightly different than the exact symbol name. -- /Jacob Carlborg
Jul 11 2017