views:

94

answers:

3

I'm using MSVC, but I plan to make my library cross platform. Right now, I have h and cpp files of classes and functions. Is making a library in MSVC as simple as adding all my files to a Visual C++ Project marked as either Static or Dynamic Library? Or must I make my classes and functions extern and whatnot?

Thanks

+4  A: 

In the case of DLLs, you'll want to specify __declspec(dllimport) or __declspec(dllexport) based on whether you're building a DLL or importing it. Consider this example:

// MyHeader.h, part of FooDLL

#ifdef BUILDING_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

void DLL_EXPORT MyFunction();

class DLL_EXPORT MyClass { 
public: 
 MyClass(); 
};

NOTE: I reordered "void" and "DLL_EXPORT" (formerly DLL_FUNCTION) as I had it mixed up before.

When including the header from within the DLL project, functions will be marked for export. When including it from another project (that doesn't have the BUILDING_DLL preprocessor definition) it will be interpreted as a DLL import. This can be applied to classes in exactly the same manner. On Linux (and possibly other similar platforms), you can safely define DLL_FUNCTION to be nothing at all, as it is not required.


Edit: and if you want your functions to be callable from C you'll obviously want to throw in ye olde extern "C" as well, to prevent the name mangling.


Edit 2: in practice, MSVC will generate a static library, too, when building a DLL. Any project that uses the DLL must link with the library (which doesn't actually contain the executable code; it's still dynamically linked as one would expect) to satisfy the linker.

Martin Törnwall
Could you show an example with a class, also, you are saying this is Windows specific, and on other platforms I'm fine? and if its static, the above is disregarded?
Milo
@Milo: edited my example to include a class as well.
Martin Törnwall
So with classes, only the class itself needs it, not its nested functions?
Milo
Yes, as far as I can remember that's all there is to it.
Martin Törnwall
If he wants the library to be cross-platform, he should make DLL_EXPORT resolve to nothing on non-Windows platforms.
asveikau
@asveikau: I already noted that. See the last paragraph before the edits.
Martin Törnwall
A: 

static or dynamic depends on the way you wan't to load it. if it is static, you will need to link it when you build your application.

for the functions, it depends again on what you wan't to do. if it's a plugin you need to declare some entry points -> extern if it's a static library you just need to include your headers in the build of the application using it.

It is not a so simple question, it depends really on what you want to do.

dzada
I just want to make a library, like GLUT, wxWidgets, etc, that can be dynamic and static
Milo
+1  A: 

Of course there are things other than described below that I'm not brining to memory right now. You might consider looking at large cross platform open source projects, like say wxWidgets which has already considered such issues.

Static

A static lib (.a|.lib) is like making a zip of your object (.o) files so you can manage them as one unit, when you compile some other program to use the static lib all the object files it needs will be compiled in.

In most cases you won't need to do anything more, you could just as well include the object files directly.

Consideration should be made for module size and how many times you might need to use the features - avoid static if you want to use the lib from more than one module in the one application.

Dynamic

You will need to specify more than your standard classes for MSVC

  • What to export using __declspec(dllexport)
  • What users of the lib can access using __declspec(dllimport)
  • will you have more than one library

Example header stub, make it unique enough so you won't clash with other libraries

// MartinsHeader.h
#ifdef BUILDING_DLL_A
#define DLL_A_EXPIMP __declspec(dllexport)
#else
#define DLL_A_EXPIMP __declspec(dllimport)
#endif

void DLL_A_EXPIMP MyFunction();
class DLL_A_EXPIMP MyClass{};

Template classes in public interfaces may raise warnings if not explicitly instantiated so all the template code is compiled.

You may want to consider PIMPL to minimise the externally visible changes to the implementation of your classes. (reduce need for users of lib to recompile for new lib)

Memory issues

The runtime becomes important in terms of who is (de)allocating what.

A) You can stick with the native memory model at which point

  • some libraries will have a bunch of different compilations for single/multi threaded debug and release modes. It will need to match the runtime of the calling module (EXE/DLL)
  • Usage of classes in the interface will often add a requirement that you use the same version of the class in both the library and the app - often means multiple compilations on version of visual C.

B) You can force memory (de)allocation by introducing factory only allocations and destruction methods so it is all performed by the library. (I'm not a big fan of this as it makes the code more difficult, but it can make runtime issues easier)

Greg Domjan