Reputation: 31
I want maintain the back compatibility of my dll, though Pimpl pattern involved that the whole class must be exported,so the name mangling caused the different compilers can not be supported, in such a case, could I offer the C compatible interface together like follow?
in the public head:
#ifdef CPPDYNAMICLINKLIBRARY_EXPORTS
# define SYMBOL_DECLSPEC __declspec(dllexport)
# define SYMBOL_DEF
#else
# define SYMBOL_DECLSPEC __declspec(dllimport)
# define SYMBOL_DEF __declspec(dllimport)
#endif
#ifdef _WIN32
#define GRAPHICAPI __stdcall
#else
#define GRAPHICAPI
#endif
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif // __cplusplus
#ifdef __cplusplus
namespace myapi{
struct SYMBOL_DECLSPEC Graphics{
Graphics();
~Graphics();
void drawLine(int,int,int,int);
void drawLine(Point,Point);
private:
struct Impl;
const Impl* impl;
}
}//end of myapi
#endif // __cplusplus
struct Graphics;
typedef struct Graphics *PGraphics;
#ifdef __cplusplus
extern "C" {
#endif
SYMBOL_DEF PGraphics GRAPHICAPI newGraphics();
SYMBOL_DEF void GRAPHICAPI deleteGraphics(PGraphics);
SYMBOL_DEF int GRAPHICAPI Graphics_drawLine4(PGraphics,int,int,int,int);
SYMBOL_DEF int GRAPHICAPI Graphics_drawLine2(PGraphics,Point,Point);
#ifdef __cplusplus
}
#endif
Also in the dll project, the def file had following definitions:
exports
newGraphics @1
deleteGraphics @2
Graphics_drawLine4 @3
Graphics_drawLine2 @4
If you did not specify the ordinals in the def file, when you add new function like Graphics_drawArc, the function Graphics_drawArc would export before Graphics_drawLine4, the old app call Graphics_drawLine4 did call the Graphics_drawArc in fact ,result in crash.
Did above solution correct?
Upvotes: 2
Views: 151
Reputation: 20878
I would hide the calling convention behind a macro in case you're porting this to a different platform where there's no notion of a __stdcall
:
#ifdef _WIN32
#define GRAPHICAPI __stdcall
#else
#define GRAPHICAPI
#endif
SYMBOL_DEF PGraphics GRAPHICAPI newGraphics();
SYMBOL_DEF void GRAPHICAPI deleteGraphics(PGraphics);
SYMBOL_DEF int GRAPHICAPI Graphics_drawLine4(PGraphics,int,int,int,int);
SYMBOL_DEF int GRAPHICAPI Graphics_drawLine2(PGraphics,Point,Point);
Other than that, I don't see any problems with it. Any ABI differences between different C++ compilers gets hidden away behind a C interface which has a fairly stable ABI.
Upvotes: 1