views:

40

answers:

2

I hav a a shared library lib.so containing a class Foo. I'm dynamically loading (with dlopen on UNIX) lib.so. After loading I want to create an instance of Foo.
Can I simply use new operator to create an object of Foo, or I would have to create an exported factory method placed in lib.so that will create that object for me?

Actually the question would be if the constructor of Foo is exported and if it could simply be called with new operator. I think that all classes and methods within shared library on UNIX are by default exported, and I don't have to export them explicitly as on Windows dll.

Besides hiding the way of creating (and possibly initializing) object of Foo, are there any other reasons for using the factory method when creating object of class contained in shared library?

A: 

There are issues with this approach. In particular, when using different versions of the same compiler for the library and the program, you have no guarantee that class member functions have the same symbol name.

Therefore, go with the factory approach, and opaque C pointer types:

// .cpp file
class Foo { ... };

// .h file
struct FooHandle;

#ifdef __cplusplus
extern "C"
{
    FooHandle* constructFoo(...);
    void releaseFoo(FooHandle*);
    int someFooMethod(FooHandle*, int param1, ...);
}
#endif

Always use C functions and opaque pointer types when exporting shared libraries.

Alexandre C.
I believe GCC maintains a compatible C++ API back to version 3.3.6. See http://stackoverflow.com/questions/3718746/g-version-compatibility
Zan Lynx
@Zan: this doesn't change the problem: a user with another compiler would not be able to import shared objects compiled with gcc.
Alexandre C.
@Alexandre: You said "different versions of the *same* compiler" which is why I made the comment.
Zan Lynx
A: 

The basic answer is yes. The devil is in the details however. On Windows, using the Microsoft C++ compiler, ALL symbols, whether they are methods, variables, etc. are not exported by default for a DLL. You need to explicitly export functions, classes, and/or global variables. I beleive this is also the case for Borlands compiler as well (I could be wrong).

With GCC it used to be the case that everything was exported by default and you couldn't really control it. As of a couple of years ago this changed with an attribute that was added (I can't recall exactly what it was called but it worked in a way similar to the equivalent Microsoft __declspec(dllexport) ).

So if you define a class and mark it as exported (however you choose to do so), it will have it's constructor exported. However, as the previous poster mentions, due to the nature of C++, the name of the symbol changes depending on what compiler you use, and also, sometimes, what version of the C++ compiler. This isn't necessarily a problem, it depends on how you want to use things, but it does mean you have to be aware of it.

Jim Crafton
visibility options and attribute...
Tomek