Exporting a class to DLL for gnu from msvc

Started by
6 comments, last by squicklid 17 years, 8 months ago
How would the def file look for exporting a class, or if not using a def file, where would you put declspec(dllexport) and/or extern "C". I searched google for answers but to no avail.
Advertisement
If you want to export a class from a DLL using VC++ then you would write the __declspec(dllexport) like so:

class __declspec(dllexport) CTest{  //blah};


I've never seen the extern "C" construct used with exporting classes so I'm not sure if it even has any effect. The primary method I've seen it used is with exporting functions from a C++ DLL. Specifying the extern "C" tells the compiler to use C style linkage for those functions so you can call them from the client application by using their original name. You only need this for C++ dlls because of the name mangling which occurs.
C++ classes are incompatible between compilers. It can't be done.

...Unless you're willing to do some serious assembly code mucking, but it's likely not worth it.
What you can do though is export 2 functions that create and destroy an instance of an interface to your class. This works because the virtual function table provides the pointers to all of the relevant code, there's no need for the class's member functions to be exported from the DLL. It goes a little something like this.....

In a common header shared by both the DLL and executable (or another DLL):
class IMyClass{public:    // Important, this ensure the correct destructor    // is called when a derived class is destroyed.    virtual ~IMyClass() =0;    // The interface to your class    virtual void DoSomething() = 0;};


In your DLL:
class MyClass : public IMyClass{public:    // The virtual keywords aren't strictly necessary,    // but I usually put them in to make it clear they're    // implementing functions from the base class    virtual ~MyClass() { ... }    virtual void DoSomething() { ... }};// I've used a raw pointer here, using smart pointers// would be better (but watch out for problems with// the DLL using a different heap, which it probably// will if you're using 2 different compilers)declspec(dllexport) IMyClass* CreateMyClass(){    return new MyClass();}// Objects should be deleted from inside the DLL since the// calling executable could be using a different heap, hence// the existence of this functiondeclspec(dllexport) void DestroyMyClass(IMyClass* obj){    delete obj;}
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
To follow on this particular subject :

How can one be sure the virtual functions in the v-table are ordered the same by different compilers ?
Quote:Original post by cnstrnd
To follow on this particular subject :

How can one be sure the virtual functions in the v-table are ordered the same by different compilers ?
You can't, but in practice, they usually are. Multiple or virtual inheritance isn't as likely to work, however.

As long as you use interfaces with no base classes and only virtual functions, and the member function parameters are interfaces or primitive types, you should be OK. This is basically a cheap version of COM. Pretty much every Windows compiler uses the same vtable layout for this reason - compatibilty with COM interfaces.

On other platforms you only have one compiler to worry about, so it doesn't really matter.
In addition, you should not put the destructor in the interface, because this allows the user to call delete, when your function calls new, which leads to mis-matched allocations.

Instead, use reference counting, or a "dispose" method on your interface.
enum Bool { True, False, FileNotFound };
Awesome. Thanks for all the help!

This topic is closed to new replies.

Advertisement