First, dont pass anything other than plain old data accross DLL boundries. i.e. structs are fine. classes are not.
Second, make sure that ownership is not transferred - i.e. any structs passed accross the dll boundry are never deallocated outside the dll. So, if you dll exports a X* GetX() function, there is a corresponding FreeX(X*) type function ensuring that the same runtime that allocated is responsible for de-allocation.
Next: Get your DLLs to link to the static runtime. Putting together a project comprimising dls from several 3rd parties, each linked to and expecting different runtimes, potentially different to the runtime expected by the app, is a pain, potentially forcing the installer software to install runtimes for 7.0, 7.1, 8.0 and 9.0 - several of which exist in different service packs which may or may not cause issues. Be kind - statically link your dll projects.
-- Edit:
You cannot export a c++ class directly with this approach. Sharing class definitions between modules means you MUST have a homogeneous runtime environment as different compilers or versions of compilers will generate decorated names differently.
You can bypass this restriction by exporting your class instead as a COM style interface... which is to say, while you cannot export a class in a runtime independent way, you CAN export an "interface", which you can easilly make by declaring a class containing only pure virtual functions...
struct IExportedMethods {
virtual long __stdcall AMethod(void)=0;
};
// with the win32 macros:
interface IExportedMethods {
STDMETHOD_(long,AMethod)(THIS)PURE;
};
In your class definition, you inherit from this interface:
class CMyObject: public IExportedMethods { ...
You can export interfaces like this by making C factory methods:
extern "C" __declspec(dllexport) IExportedClass* WINAPI CreateMyExportedObject(){
return new CMyObject;
}
This is a very lightweight way of exporting compiler version and runtime independent class versions. Note that you still cannot delete one of these. You Must include a release function as a member of the dll or the interface. As a member of the interface it could look like this:
interface IExportedMethods {
STDMETHOD_(void) Release(THIS) PURE; };
class CMyObject : public IExportedMethods {
STDMETHODIMP_(void) Release(){
delete this;
}
};
You can take this idea and run further with it - inherit your interface from IUnknown, implement ref counted AddRef and Release methods as well as the ability to QueryInterface for v2 interfaces or other features. And finally, use DllCreateClassObject as the means to create your object and get the necessary COM registration going. All this is optional however, you can easilly get away with a simple interface definition accessed through a C function.