0

I am the developer of a c++ library on Linux, Windows and osX. Since osX now does not handle properly anonymous exceptions, I considered cleanly marking the symbols that need to be exported. Following these explanations I defined two macros: FOO_API and FOO_LOCAL for marking the symbols. Now I have the following problems:

I define each class in its own file (because I don't want 1000+ long files). If class A is only used in my library, it would make sense to mark it with FOO_LOCAL. But if class B has a private member of type A, and class B is FOO_API, then I receive a compiler warning and the linking fails (symbol not found). That seems to defy the whole point of these export attributes. So, what should it be? I mark my class with something like class FOO_LOCAL A {...} Is this right?

Is there also no way to have all private members local? (since they are private, they are not supposed to be directly accessed) This would make the marking process less tedious...

Finally, when I mark for example my exception classes, it compiles and run properly, but showing the symbols (nm -C -D my_lib.so) shows that all the symbols are still there...

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
mathias
  • 495
  • 4
  • 6
  • I don't understand... class members variables don't have linkage, unless they are static. If that the case? – rodrigo Sep 19 '12 at 19:12
  • @rodrigo I guess the problem is though that these are 'seen' when including the API header file(s) and creating instances of the API classes (which might require allocating members on the stack). Maybe using pointers to forward declared local classes in the API classes would also solve the problem. – πάντα ῥεῖ Sep 19 '12 at 19:20
  • @g-makulik: That makes no sense at all. Visibility is a property of the linkage, so if there is no linkage there is no problem with visibility. Unless the constructor of A is inline, of course... – rodrigo Sep 19 '12 at 19:29
  • @rodrigo Doesn't that depend on how s.th. like `__attribute__ ((dllexport))` or `__declspec(dllexport)` works with the actual compiler/linker implementation rather than the scope specifications of class members? – πάντα ῥεῖ Sep 19 '12 at 19:59
  • @g-makulik: No, because the _client_ does not access the member by name, but by offset from the start of the class. A different thing happens with member functions, and maybe that is the OP problem. – rodrigo Sep 19 '12 at 20:03
  • @rodrigo What about inline implementations accessing the 'should be hidden' lib local class members, you already mentioned that regarding constructors? I think the pimpl idiom is a robust recipe to avoid such flaws. – πάντα ῥεῖ Sep 19 '12 at 20:09
  • Sorry, I messed up my explanations: the compiling/linking that fails is when compiling/linking to an application using the library. And I finally understood better what happened: there is an explicit destructor for class A, so when deconstructing object B, it needs to call the destructor of object A (and the linking could not be resolved). I added FOO_API in to the destructors and now have something that properly compile, link and run. But the output of nm -C -D is exactly the same is without any of this, so I wonder if it actually does something... – mathias Sep 20 '12 at 10:02

1 Answers1

1

You can use the pimpl idiom to hide the library internal implementation of API classes from the public (and thus when linking the library).

S.th. like:

B.hpp:

class BImpl;

class FOO_API B
{
public:
    // Public stuff
    B();
    ~B();

    void foo();
private:
    BImpl* bimpl;
};

B.cpp:

#include "B.hpp"
#include "A.hpp"

struct BImpl
{
    void foo()
    {
        // Do something with 'a'
    }

    A a;
};

B::B()
: bimpl(new BImpl())
{
}

B::~B()
{
    delete bimpl;
}

void B::foo()
{
    bimpl->foo();
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • I prefer to avoid using this kind of construct, because some sections of the code are performance critical (and for code clarity as well). And since my code is open source, I don't need to hide anything from the evil eyes of a competitor... – mathias Sep 20 '12 at 09:32