28

私のC/C ++開発のほとんどは、モノリシックモジュールファイルを含み、クラスはまったく含まれていません。したがって、通常、アクセス可能な関数を使用してDLLを作成する必要がある場合は、標準__declspec(dllexport)ディレクティブを使用してそれらをエクスポートします。LoadLibrary()次に、ヘッダーとlibファイルを介して、またはコンパイル時に動的にアクセスします。

クラス全体(およびそのすべてのパブリックメソッドとプロパティ)をエクスポートする場合、これをどのように行いますか?

実行時にそのクラスを動的にロードすることは可能ですか?もしそうなら、どのように?

コンパイル時のリンク用のヘッダーとライブラリをどのように使用しますか?

4

6 に答える 6

17

DLLとDLLを使用するモジュールをビルドするときは、一方と他方を区別するために使用できるある種の#defineを用意し、クラスヘッダーファイルで次のようなことを行うことができます。

#if defined( BUILD_DLL )
    #define IMPORT_EXPORT __declspec(dllexport)
#else
    #define IMPORT_EXPORT __declspec(dllimport)
#endif
class IMPORT_EXPORT MyClass {
    ...
};

編集:crashmstrは私をそれに打ち負かしました!

于 2008-08-26T13:26:55.560 に答える
17

遅延バインディングはどうですか?LoadLibrary() と GetProcAddress() でロードするのと同じように?私は実行時にライブラリをロードできることに慣れていますが、ここでそれができれば素晴らしいと思います。

したがって、DLL をロードするには 2 つの方法があります。1 つ目は、DLL から 1 つまたは複数のシンボル (たとえば、クラス名) を参照し、適切なインポート .LIB を提供して、リンカーにすべてを理解させることです。

2 つ目は、LoadLibrary を介して DLL を明示的にロードすることです。

C レベル関数のエクスポートでは、どちらの方法でも問題なく機能します。リンカーに処理させるか、メモしたように GetProcAddress を呼び出すことができます。

しかし、エクスポートされたクラスに関しては、通常、最初の方法、つまり暗黙的に DLL にリンクする方法のみが使用されます。この場合、DLL はアプリケーションの開始時にロードされ、DLL が見つからない場合、アプリケーションはロードに失敗します。

DLL で定義されたクラスにリンクし、その DLL をプログラムの開始後に動的にロードする場合は、次の 2 つのオプションがあります。

  1. 特別なファクトリ関数を使用してクラスのオブジェクトを作成します。これは、内部で (ほんの少しの) アセンブラを使用して、新しく作成されたオブジェクトを適切なオフセットに「接続」する必要があります。これは、明らかに、DLL がロードされた後、実行時に実行する必要があります。このアプローチの適切な説明は、こちらにあります

  2. 遅延読み込み DLLを使用します。

すべてのことを考慮して...おそらく暗黙のリンクを使用する方が良いでしょう。その場合、上記のプリプロセッサ手法を確実に使用する必要があります。実際、Visual Studio で新しい DLL を作成し、「シンボルのエクスポート」オプションを選択すると、これらのマクロが作成されます。

幸運を...

于 2008-08-26T15:07:29.330 に答える
13

DLL から C++ クラスをエクスポートするための簡単な作業例を追加します。

以下の例は、dll と exe がどのように相互に作用するかについての簡単な概要のみを示しています (自明です) が、製品コードに変更するには、さらに多くのことを追加する必要があります。

完全なサンプル例は 2 つの部分に分かれています

A. .dll ライブラリ (MyDLL.dll) の作成

B. .dll ライブラリを使用するアプリケーションの作成 (アプリケーション)。

A. .dll プロジェクト ファイル (MyDLL.dll):

1.dllHeader.h

#ifdef  MYDLL_EXPORTS 
#define DLLCALL __declspec(dllexport)   /* Should be enabled before compiling 
                                           .dll project for creating .dll*/
#else
#define DLLCALL __declspec(dllimport)  /* Should be enabled in Application side
                                          for using already created .dll*/
#endif

// Interface Class
class ImyMath {
public:
    virtual ~ImyMath() {;}
    virtual int Add(int a, int b) = 0;
    virtual int Subtract(int a, int b) = 0;
};

// Concrete Class
class MyMath: public ImyMath {
public:
    MyMath() {}
    int Add(int a, int b);
    int Subtract(int a, int b);
    int a,b;
};

//  Factory function that will return the new object instance. (Only function
//  should be declared with DLLCALL)
extern "C" /*Important for avoiding Name decoration*/
{
    DLLCALL ImyMath* _cdecl CreateMathObject();
};

// Function Pointer Declaration of CreateMathObject() [Entry Point Function]
typedef ImyMath* (*CREATE_MATH) ();

2.dllSrc.cpp

#include "dllHeader.h"

// Create Object
DLLCALL ImyMath* _cdecl CreateMathObject() {
    return new MyMath();
}

int MyMath::Add(int a, int b) {
    return a+b;
}

int MyMath::Subtract(int a, int b) {
    return a-b;
}

B. 作成済みの .dll ファイルをロードしてリンクするアプリケーション プロジェクト:

 #include <iostream>
#include <windows.h>
#include "dllHeader.h"

int main()
{
    HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); // L".\Debug\MyDLL.dll"

    if (hDLL == NULL) {
        std::cout << "Failed to load library.\n";
    }
    else {
        CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
        ImyMath* pMath = pEntryFunction();
        if (pMath) {
            std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
            std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
        }
        FreeLibrary(hDLL);
    }
    std::cin.get();
    return 0;
}
于 2014-06-24T10:48:41.920 に答える
12

インポートまたはエクスポート用のコードをマークするためにいくつかのマクロを使用します

#ifdef ISDLL
#define DLL __declspec(dllexport)
#endif

#ifdef USEDLL
#define DLL __declspec(dllimport)
#endif

次に、ヘッダーファイルでクラスを宣言します。

クラスDLLMyClassToExport{...}

次に#define ISDLL、ライブラリでUSEDLL、クラスを使用する場所にヘッダーファイルをインクルードする前に。

で作業するために何か別のことをする必要があるかどうかはわかりませんLoadLibrary

于 2008-08-26T13:26:01.133 に答える
7

最近、まったく同じ質問を自問し、調査結果をブログ投稿にまとめました。役に立つかもしれません。

DLL から C++ クラスをエクスポートする方法LoadLibrary、および で動的にロードする方法について説明し、メモリ管理、名前マングリング、呼び出し規約など、これに関連するいくつかの問題について説明します。

于 2011-09-17T03:22:02.933 に答える
0

エクスポートするクラスに vtable を配置する場合は、インターフェイスを返す関数をエクスポートし、クラスを .dll に実装してから、それを .def ファイルに配置できます。宣言のトリックが必要になる場合がありますが、それほど難しくはありません。

COMのように。:)

于 2008-08-27T13:50:57.537 に答える