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 の前にエクスポートされ、古いアプリの呼び出し Graphics_drawLine4 が Graphics_drawArc を実際に呼び出し、結果としてクラッシュします。

上記の解決策は正しいですか?

4

1 に答える 1

1

の概念がない別のプラットフォームにこれを移植する場合に備えて、呼び出し規約をマクロの背後に隠します__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);

それ以外には、問題はありません。異なる C++ コンパイラ間の ABI の違いは、かなり安定した ABI を持つ C インターフェイスの背後に隠されます。

于 2013-11-06T05:35:01.050 に答える