www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - pragma(mangle) on types

reply Jacob Carlborg <doob me.com> writes:
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
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
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
prev sibling parent reply Moritz Maxeiner <moritz ucworks.org> writes:
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
parent reply Moritz Maxeiner <moritz ucworks.org> writes:
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:
 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).
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",
Jul 11 2017
parent Jacob Carlborg <doob me.com> writes:
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