2

我想保持我的 dll 的向后兼容性,虽然 Pimpl 模式涉及必须导出整个类,所以名称修改导致无法支持不同的编译器,在这种情况下,我可以像下面一样提供 C 兼容接口?

在公共头:

#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 

同样在 dll 项目中,def 文件具有以下定义:

exports
         newGraphics    @1
         deleteGraphics    @2
         Graphics_drawLine4    @3
         Graphics_drawLine2   @4

如果你在def文件中没有指定序数,当你添加Graphics_drawArc这样的新函数时,函数Graphics_drawArc会在Graphics_drawLine4之前导出,旧的app调用Graphics_drawLine4实际上调用了Graphics_drawArc,导致crash。

上述解决方案是否正确?

4

1 回答 1

1

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.

于 2013-11-06T05:35:01.050 回答