tags:

views:

4379

answers:

8

Most of my C/C++ development involves monolithic module files and absolutely no classes whatsoever, so usually when I need to make a DLL with accessible functions I just export them using the standard __declspec(dllexport) directive. Then access them either dynamically via LoadLibrary() or at compile time with a header and lib file.

How do you do this when you want to export an entire class (and all it's public methods and properties)?

Is it possible to dynamically load that class at runtime and if so, how?

How would you do it with a header and lib for compile time linking?

+5  A: 

I use some macros to mark the code for import or export

#ifdef ISDLL
#define DLL __declspec(dllexport)
#endif

#ifdef USEDLL
#define DLL __declspec(dllimport)
#endif

Then declare the class in a header file:

class DLL MyClassToExport { ... }

Then #define ISDLL in the libary, and USEDLL before including the header file in the place you want to use the class.

I don't know if you might need to do anything differently for working with LoadLibrary

crashmstr
+2  A: 

When you build the DLL and the module that will use the DLL, have some kind of #define that you can use to distinguish between one and the other, then you can do something like this in your class header file:

#if defined( BUILD_DLL )
    #define IMPORT_EXPORT __declspec(dllexport)
#else
    #define IMPORT_EXPORT __declspec(dllimport)
#endif
class IMPORT_EXPORT MyClass {
    ...
};

Edit: crashmstr beat me to it!

Graeme Perrow
A: 

Ok....so that sort of made sense...but how do I import it? And what about class properties? Any chance of getting a more complete example?

Adam Haile
A: 

Sorry, we missed the build steps. When you build your DLL (say testdll.dll), make sure the class is marked as __declspec(dllexport). When you link it, the linker will create both the DLL (testdll.dll) and an import library testdll.lib.

When you build your program, include the same header file but make sure the class is marked as __declspec(dllimport). You can then use the class as if it were built into the executable. Link it with testdll.lib, and when your program runs, it will look for testdll.dll and load it (and fail to run if it cannot be found).

Graeme Perrow
A: 

when your program runs, it will look for testdll.dll and load it (and fail to run if it cannot be found).

What about late-binding? As in loading it with LoadLibrary() and GetProcAddress() ? I'm used being able to load the library at run time and it would be great if you could do that here.

Adam Haile
Is this a piece of history, before there were "comments"?
bobobobo
yes, there were no comments in 2008
Adam Haile
+1  A: 

Hmmm.... not sure about that one. I know that for C++ functions you need specify the mangled function name when you try to import it, which is a big pain. I've never tried to import a class that way, and I don't know if it can even be done. You might be able to get to the methods of the class that way (specifying the mangled name), but I don't know about the properties, unless you have get/set methods for each property.

You might need to write C wrappers around the methods and export those.

Graeme Perrow
+4  A: 

What about late-binding? As in loading it with LoadLibrary() and GetProcAddress() ? I'm used being able to load the library at run time and it would be great if you could do that here.

So there are two ways to load the DLL. The first is to reference one or more symbols from the DLL (your classname, for example), supply an appropriate import .LIB and let the linker figure everything out.

The second is to explicitly load the DLL via LoadLibrary.

Either approach works fine for C-level function exports. You can either let the linker handle it or call GetProcAddress as you noted.

But when it comes to exported classes, typically only the first approach is used, i.e., implicitly link to the DLL. In this case the DLL is loaded at application start time, and the application fails to load if the DLL can't be found.

If you want to link to a class defined in a DLL, and you want that DLL to be loaded dynamically, sometime after program initiation, you have two options:

  1. Create objects of the class using a special factory function, which internally will have to use (a tiny bit of) assembler to "hook up" newly created objects to their appropriate offsets. This has to be done at run-time AFTER the DLL has been loaded, obviously. A good explanation of this approach can be found here.

  2. Use a delay-load DLL.

All things considered... probably better to just go with implicit linking, in which case you definitely want to use the preprocessor technique shown above. In fact, if you create a new DLL in Visual Studio and choose the "export symbols" option these macros will be created for you.

Good luck...

James D
A: 

If you're willing to put a vtable in the class you're exporting, you can export a function that returns an interface and implement the class in the .dll, then put that in the .def file. You might have to do some declaration trickery, but it shouldn't be too hard.

Just like COM. :)

MSN

Mat Noguchi