Boost logo

Boost :

Subject: Re: [boost] [Boost.DLL] Formal Review request
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2014-10-06 19:51:37


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_at_adl_barrier_at_foo@
> @YA?AV?$variant_at_HFUvoid__at_0detail@boost@@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023
> @U1023_at_U1023@U1023_at_U1023@U10
> 23_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023@@boost@@V45_at_0@Z@@
> .?AU?$printer@$E?export_me_variable_at_adl_barrier_at_foo@@3V?$variant_at_HFUvoid_
> @0detail_at_boost@@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023
> @U1023_at_U
> 1023_at_U1023@U1023_at_U1023@U1023_at_U1023@@boost@@A@@
>
> While we still need the following:
> Windows:
> ?export_me_function_at_adl_barrier_at_foo@@YA?AV?$variant_at_HFUvoid__at_0detail@boost
> @@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023
> @U1023_at_U1
> 023_at_U1023@U1023_at_U1023@@boost@@V34_at_0@Z
> ?export_me_variable_at_adl_barrier_at_foo@@3V?$variant_at_HFUvoid__at_0detail@boost
> @@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023@U1023_at_U1023
> @U1023_at_U1023
> @U1023_at_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/



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk