
On 5 Oct 2014 at 10:12, Antony Polukhin wrote: Let me reorg this for you ...
Code from above will output: Linux: 8printer2ILZN3foo11adl_barrier18export_me_functionEN5boost7variantIisNS2_6detail7variant5void_ES6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_S6_EES7_EE 7printerILZN3foo11adl_barrier18export_me_variableEEE
While we still need the following: Linux: _ZN3foo11adl_barrier18export_me_functionEN5boost7variantIisNS1_6detail7variant5void_ES5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_EES6_ _ZN3foo11adl_barrier18export_me_variableE
Code from above will output: Windows: .?AU?$printer2@$1?export_me_function@adl_barrier@foo@ @YA?AV?$variant@HFUvoid_@0detail@boost@@U1023@U1023@U1023@U1023@U1023@U1023 @U1023@U1023@U1023@U1023@U10 23@U1023@U1023@U1023@U1023@U1023@U1023@@boost@@V45@0@Z@@ .?AU?$printer@$E?export_me_variable@adl_barrier@foo@@3V?$variant@HFUvoid_ @0detail@boost@@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023 @U1023@U 1023@U1023@U1023@U1023@U1023@U1023@@boost@@A@@
While we still need the following: Windows: ?export_me_function@adl_barrier@foo@@YA?AV?$variant@HFUvoid_@0detail@boost @@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023 @U1023@U1 023@U1023@U1023@U1023@@boost@@V34@0@Z ?export_me_variable@adl_barrier@foo@@3V?$variant@HFUvoid_@0detail@boost @@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023@U1023 @U1023@U1023 @U1023@U1023@U1023@@boost@@A
Looks like such method is not very good, function definition has changed (Linux:5 was transformed into 6, 1 was tranformed into 2;
Yes, that's the name compression scheme used to avoid repetition, so they use numbers to refer to earlier decls to avoid spelling them out in full each time. When wrapped with printer, you can safely subtract one from all of those numbers as you know printer will consume the first number. For Itanium, an S prefix means "use the n-th decl from the beginning".
Windows: V34 changed into V45)... I'm afraid that there'll be more surprises
For the same reason, earlier mangled decls int and short are offset by one, hence the V34 => V45. There is an alternative, but it is slightly evil: how about one only provides type safety for imported functions and variables which are in at least one namespace level? One then can replace one of those namespaces with printer<>, and therefore not modify the remainder of the mangling? To test that, I modified your original program like this: #include <typeinfo> #include <iostream> #include <utility> struct void_ { }; template<class A, class B, class C=void_, class D=void_, class E=void_> struct variant : std::pair<A, B> { variant() { } variant(A a, B b) : std::pair<A, B>(a, b) {} }; namespace foo { namespace adl_barrier { __declspec(dllexport) variant<int, short> export_me_function(variant<int, short>, variant<int, short>) { return variant<int, short>(0, 0); } __declspec(dllexport) variant<int, short> export_me_variable; } // namespace adl_barrier using adl_barrier::export_me_function; using adl_barrier::export_me_variable; } // These being the dummy types purely used to get the mangling from them namespace $$magic$$_adl_barrier { extern variant<int, short> export_me_function(variant<int, short>, variant<int, short>); extern variant<int, short> export_me_variable; } template <variant<int, short>& var> struct $$magic$$_vprinter {}; template <variant<int, short>(&var)(variant<int, short>, variant<int, short>)> struct $$magic$$_fprinter {}; int main() { std:: cout << typeid($$magic$$_fprinter<$$magic$$_adl_barrier::export_me_function>). name() << std::endl; std:: cout << typeid($$magic$$_vprinter<$$magic$$_adl_barrier::export_me_variable>). name() << std::endl; } Prints: 18$$magic$$_fprinterILZN21$$magic$$_adl_barrier18export_me_functionE7v ariantIis5void_S2_S2_ES3_EE 18$$magic$$_vprinterILZN21$$magic$$_adl_barrier18export_me_variableEEE Exported: __ZN3foo11adl_barrier18export_me_functionE7variantIis5void_S2_S2_ES3_ __ZN3foo11adl_barrier18export_me_variableE ... which looks bang on. Simply replace the 8fprinter with 3foo and remove the $$magic$$_. In case that seems too hacky, another option is to name the decl for the printer to be identical to the first namespace, that way the decl gets reused instead of incrementing the back reference count. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/