1

わかりました、Dll Hell と呼ばれる理由がわかり始めました。
これは私が得たコードです

// API.h file
#ifdef EXPORTS
    #define API __declspec(dllexport)
#else
    #define API __declspec(dllimport)
#endif

struct API IClass {
   virtual void foo() = 0;
}

extern "C" API IClass* CreateClass(const char* type);

// Impl1.h
class Impl1: public IClass
{
   //...
}

// API.cpp file
#include "Impl1.h"
#include "Impl2.h"
#include "ImplX.h"

extern "C" API IClass* CreateClass(const char* type)
{
    if (type == "type1")
        return new Impl1();

    // ...
    return 0;
}

リンカーの警告が表示される

warning LNK4217: locally defined symbol ??0IClass@DG@@QAE@XZ (public: __thiscall IClass::IClass(void)) imported in function... 

これらのシンボルをすべての Impl にインポートしたため、これが発生していることは理解していますが、API の一部であるファクトリでコンパイルしているため、ローカルになっています。

1) 警告を無視する必要がありますか、またはこれにアプローチする別の方法がありますか?
2) デフォルトの __thiscall のままにするか、 __stdcall に変更する必要がありますか?

編集
エクスポートしないIClassと、警告を削除するのに役立ちました。
別の問題が発生し、同じ方法でこれを修正できるかどうかわかりません。method も持っている
としましょう。 クライアントがインスタンスを作成できるようにしたい場合は、それを dll にエクスポートする必要があり、impl 内の元の問題に戻ります。それらの作成関数も作成しない限り、これは単純なデータ構造体のオーバーヘッドが少し大きいようです。IClassvirtual bar(IData* data) = 0
IData

基本的に問題は、IDataクライアントを DLL にエクスポートせずにクライアントに公開するにはどうすればよいかということです。

4

1 に答える 1

2

COM のようなものを使用している場合: 経由でインターフェイスをエクスポートする必要はありません。

__declspec(dllexport|import).

呼び出し規約はかなり古い概念であり、x64 に関連しています (Windows と UNIX の両方に 64 ビットの呼び出し規約が 1 つしかありません!) 32 ビットでの選択は、__cdeclまたは__stdcall. 一番のルールは次のとおりです。一貫性を保ちましょう。これらの規則はどちらもそれ自体は問題ありません。(あなたが使用するつもりでない限り(va_argsそれらは純粋な悪であるため、使用すべきではありません)...)

__stdcallは COM と WinAPI で使用されますが、標準ライブラリは主に を使用してい__cdeclます。パフォーマンスに関しては、まったく無関係です (呼び出し規約の速度の違いについて、stackoverflow のどこかに投稿があります)。

この警告は、コンストラクターではなくクラスをエクスポートしているという事実に起因する可能性があるため、クラスをエクスポートしないことをお勧めします...

于 2012-07-25T11:09:54.170 に答える