This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: Problem with flag -fvisibility=hidden and share library
- From: "John (Eljay) Love-Jensen" <eljay at adobe dot com>
- To: José Luis Pulido Burbano <josel2820 at gmail dot com>, GCC-help <gcc-help at gcc dot gnu dot org>
- Date: Fri, 8 May 2009 04:57:17 -0700
- Subject: Re: Problem with flag -fvisibility=hidden and share library
Hi José,
> Hello, "I must"(the Makefile of my library does obtain the flags for
> to compile from other Makefile , I can't to avoid this process ) to
> use the flag -fvisibility=hidden in the compilation of my share
> library, but this make that I have problems with the use of the
> library , exist someone form , for example using macros or other
> mecanism for to avoid the efect of this flag in the compilation of my
> share library,thanks in advance.
I do what you are trying to do (using the -fvisibility=hidden flag), all the
time. I've actually got that "baked" into gcc, by using a mygcc shell
script which specifies that flag and enables most warnings and ludicrously
noisy levels (I wish there was a -Wall-all-all to enabled all toggle
warnings).
It's not too hard, but does require you to touch up your code.
I hope the example below is sufficient to help you understand. I'm
combining it with the PImpl-via-inheritance, to make the example a little
more than trivial (but not by much). Not using a namespace, in real world
C++ code you probably should use a namespace here.
Let's say I have these source code files:
FooExport.h -- the magic you are looking for
FooPublic.h -- my public API
FooPrivate.h -- my internals, not shipped with the DLL
Foo.cpp -- the source, also not shipped
------ FooExport.h ------
#ifndef FooExport_h
#define FooExport_h
#define EXPORT __attribute__((visibility("default")))
#define CLASS_EXPORT __attribute__((visibility("default")))
#endif
-------------------------
EXPORT and CLASS_EXPORT are both defined, to make it easier to work with
other platforms (e.g., Microsoft Windows) which use a different convention.
The CLASS_EXPORT is used to export the RTTI typeinfo, which is vital for
dynamic_cast, catching exceptions.
The EXPORT is used to export free standing functions, global variables,
methods (object functions), and class (static) functions.
------ FooPublic.h ------
#ifndef FooPublic_h
#define FooPublic_h
#include "FooExport.h"
#include <memory>
class CLASS_EXPORT Foo
{
public:
EXPORT virtual ~Foo();
EXPORT void Something();
private:
virtual void DoSomething() = 0;
};
EXPORT std::auto_ptr<Foo> NewFoo();
#endif
-------------------------
The Something / DoSomething trick makes it easier to debug Something, by
setting a breakpoint on the non-virtual Something.
The destructor is virtual, otherwise the std::auto_ptr<Foo> won't properly
destruct.
The std::auto_ptr specified in the NewFoo factory function is to convey, in
code (rather than in a comment), explicit transfer of ownership (and hence
lifetime management and memory management).
Some bugs left in the Foo class:
+ the compiler provided synthetic copy-constructor was not squelched.
+ the compiler provided synthetic assignment-operator was not squelched.
------ FooPrivate.h ------
#ifndef FooPrivate_h
#define FooPrivate_h
#include "FooPublic.h"
class PrivateFoo
:
public Foo
{
public:
PrivateFoo(
int inX,
int inY);
virtual ~PrivateFoo();
private:
virtual void DoSomething();
int x;
int y;
};
#endif
-------------------------
------ Foo.cpp ------
#include "FooPublic.h"
#include "FooPrivate.h"
#include <iostream>
std::auto_ptr<Foo> NewFoo()
{
std::cout << "NewFoo factory says 'making the foo'" << std::endl;
std::auto_ptr<Foo> result(new PrivateFoo(7, 100));
return result;
}
void Foo::Something()
{
std::cout << "Foo says 'Something'" << std::endl;
DoSomething();
}
Foo::~Foo()
{
std::cout << "Foo says 'bye bye'" << std::endl;
}
PrivateFoo::PrivateFoo(
int inX,
int inY)
:
x(inX),
y(inY)
{
std::cout << "PrivateFoo says 'hello'" << std::endl;
}
void PrivateFoo::DoSomething()
{
std::cout << "PrivateFoo says 'DoSomething'" << std::endl;
std::cout << "x:" << x << " y:" << y << std::endl;
}
PrivateFoo::~PrivateFoo()
{
std::cout << "PrivateFoo says 'bye bye'" << std::endl;
}
-------------------------
CAVEAT: I did not compile and run the above code. Just off the cuff.
Probably has embarrassing bugs, typos, and omissions.
Sincerely,
--Eljay