Hello I have problem with using std::locale::facet
s from DLL.
It seems that locale "id" is not shared between DLL and the source. has_facet
reports
that "facet exists" on different kind of facet. And facet ids reported incorrectly.
In the below example, foo::id
and bar::id
are seems to be the same and the has_facet
reports true
on uninstalled facet.
The question is: How to workaround this issue?
This is a simple example:
facet.h:
#include <locale>
#ifdef DLL_EXPORT
# ifdef FOO_SOURCE
# define API __declspec(dllexport)
# else
# define API __declspec(dllimport)
# endif
#else
# define API
#endif
class API bar : public std::locale::facet {
public:
bar(size_t refs=0) :
std::locale::facet(refs)
{
}
int test() const;
static std::locale::id id;
virtual ~bar() {}
};
class API foo : public std::locale::facet {
public:
foo(size_t refs=0) :
std::locale::facet(refs)
{
}
int test() const;
static std::locale::id id;
virtual ~foo() {}
};
std::locale API create();
Facet.cpp:
#define FOO_SOURCE
#include "facet.h"
std::locale::id foo::id;
int foo::test() const
{
return id._M_id();
}
std::locale::id bar::id;
int bar::test() const
{
return id._M_id();
}
std::locale API create()
{
std::locale l(std::locale(),new foo());
return l;
}
And simple test program:
#include <iostream>
#include "facet.h"
using namespace std;
int main()
{
std::locale l=create();
std::cout << has_facet<foo>(l) << std::endl;
std::cout << has_facet<bar>(l) << std::endl;
std::cout << foo::id._M_id() << std::endl;
std::cout << bar::id._M_id() << std::endl;
std::cout << use_facet<foo>(l).test() << std::endl;
return 0;
}
If I compile it:
g++ -DDLL_EXPORT -shared facet.cpp -o facet.dll -Wl,--out-implib,libfacet.dll.a
g++ -DDLL_EXPORT test.cpp libfacet.dll.a
And run: I get true locale l having both foo
and bar
, when this is incorrect
and when I compile statically:
g++ test.cpp facet.cpp
Everything works fine.
Form what I had found, the class std::locale::id
defined as:
class locale::id {
...
// Last id number assigned.
static _Atomic_word _S_refcount;
...
};
And it is not exported... So static member _S_refcount
is not shared between DLL and
the executable (damned dlls).
Is there any way to workaround this issue?
Solution for MinGW:
Use gcc 4.x, under MinGW + gcc-4.4 it works fine.
Still looking for solution for Cygwin, gcc-4.3 fails to compile and run this code... Some dll mess.