VCとVBでC++DLLを呼び出す方法を一歩一歩教えます

12864 ワード

Step by Step: Calling C++ DLLs from VC++ and VB
VCとVBでC++DLLを呼び出す方法を一歩一歩教えます.
作者Hans Dietrich翻訳灰皿
紹介する
このチュートリアルでは、一般的にDLLを使用する4つの方法について説明します.
Part 1
VC++アプリケーションからC++DLLの関数を呼び出す
VC++アプリケーションからC++DLLのクラスを呼び出す
Part 2
VBアプリケーションからC++DLLの関数を呼び出す
Part 3
VBアプリケーションからC++DLLのクラスを呼び出す
Part 4
VC++アプリケーションから動的にC++DLLを呼び出す関数
VC++アプリケーションからC++DLLの関数を呼び出す
Visual Studio 6は、関数やクラスを含む動的接続ライブラリ(DLL)の作成を容易にする.
最初のステップ
Visual Studioを開き、File|Newメニュー項目:screenを選択します.width-500)this.style.width=screen.width-500;">Win 32 Dynamic Link Libraryを選択し、プロジェクト名を入力してOK.screen.width-500)this.style.width=screen.width-500をタップします.">A DLL that exports some symbolsを選択し、Finishをクリックします.File Viewでは、screenというプロジェクトファイルが表示されます.width-500)this.style.width=screen.width-500;">
ステップ2
Testでcppでは、次のコードが表示されます.
// Test.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "Test.h"

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}


// This is an example of an exported variable
TEST_API int nTest=0;

// This is an example of an exported function.
TEST_API int fnTest(void)
{
    return 42;
}

// This is the constructor of a class that has been exported.// see Test.h for the class definition
CTest::CTest()
{
    return;
}

Test.cpp
含むfnTest CTest::CTest
.
もしあなたが今編集したらdll、あなたは他の人に
VC++
アプリケーションが直接呼び出す
DLL.  
その他を許可
VC++
プログラム呼び出しのキーメカニズム
?( key mechanism)
に含まれる
Test.h

:
// The following ifdef block is the standard way of creating macros// which make exporting from a DLL simpler. All files within this DLL// are compiled with the TEST_EXPORTS symbol defined on the command line.// This symbol should not be defined on any project that uses this DLL.// This way any other project whose source files include this file see // TEST_API functions as being imported from a DLL, whereas this DLL// sees symbols defined with this macro as being exported.#ifdef TEST_EXPORTS#define TEST_API __declspec(dllexport)#else#define TEST_API __declspec(dllimport)#endif// This class is exported from the Test.dllclass TEST_API CTest 
{
public:
    CTest(void);
    // TODO: add your methods here.
};

extern TEST_API int nTest;

TEST_API int fnTest(void);

何があったの?ifdef TEST_EXPORTSってどういう意味ですか?TEST_EXPORTSはどこで定義されていますか?TEST_EXPORTSが定義されると、TEST_APIは__として定義される.declspec(dllexport)(DLLエクスポート)では、そうでない場合は__と定義されます.declspec(dllimport)(DLLインポート).これは、後述Ctestクラスがエクスポートクラスであるかインポートクラスであるかに影響する.これは、もし私たちがエクスポートする必要がある場合、TEST_EXPORTS.を定義しなければならないことを意味します.VC++アプリケーションがこのDLLにアクセスするとき、Testを定義することができます.libはDLLのエクスポート記号を含むリンクされている.
ステップ3TEST_EXPORTS
どこで定義されているのでしょうか
? DLL wizard
いやなことをした
,
それはTEST_EXPORTS
命令ラインに入れた

選択
Project | Settings | C/C++ | General,
プロジェクトオプションが表示されます
: screen.width-500)this.style.width=screen.width-500;">
もちろん、この方法は実行可能です.しかし、それはうっかりしやすく、メンテナンス上のトラブルを引き起こす可能性があります.私ははっきりした定義が好きです.TEST_EXPORTS:プロジェクトの選択肢から/D「TEST_EXPORTS」を外して、Test.cppで定義します://Test.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#define TEST_EXPORTS//<==ADD THIS LINE#include"Test.h"BOOL APIENTRY DllMain(HANDLE hModule,DWORDul_reason_for_call,LPVOID lpReserved){...注意#define TEST_EXPORTSは#include"Test.h"前の方したがって、ヘッダファイルに定義されます.今、以前のようにTestを再コンパイルすることができます.dll、他のVCアプリケーションで呼び出すことができるDLLを得る.
 
ステップ4
DLLの関数を呼び出すにはどうすればいいですか?例を挙げて、VSで例を作成します.MFC AppWizard(exe)を選択し、項目名を入力し、OKをクリックします.ダイアログベースを選択します.それからXXXDlgを開く.cpp(XXXはあなたの工事の名前です.)OnInitDialog()メンバー関数を見つけて、次のコードを入力します.
    .
    .
    .
    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    // code to test Test.dll function:
    int n = fnTest();                    // <=== ADD THIS LINE

    // code to test the CTest class:
    CTest test;                          // <=== ADD THIS LINE
    
    return TRUE;  // return TRUE  unless you set the focus to a control
}

ステップ5
私たちはまだコードを書き終わっていません.
,
今すぐ
Test.h
これ
DLL
のヘッダファイルが含まれます.
// TestExeDlg.cpp : implementation file//#include "stdafx.h"#include "TestExe.h"#include "TestExeDlg.h"#include "Test.h"                        // <=== ADD THIS LINE
.
.
.

ステップ6
急いでプレゼンテーションをしたいなら、DLLのtestをコピーするだけを試してみるかもしれません.hあなたのプロジェクトディレクトリに行くと、コンパイラがそれを見つけます.しかし、プロジェクトが大きい場合、これは良いアイデアではありません.DLLファイルを更新すると、危険にさらされる可能性があります.例えばexeのディレクトリにコピーするのを忘れた.ここでは、Project|Settings|C/C+|Settings|Preprocessorを選択し、Additional include directories:(DLLエンジニアリングのディレクトリ)screenを追加する簡単な方法があります.width-500)this.style.width=screen.width-500;">
ヒント:DLLプロジェクトとEXEプロジェクトが同じプロジェクトディレクトリを持つと仮定する.
今私がコンパイルしたとき、私はlinker errorsを手に入れました!!Deleting intermediate files and output files for project 'TestExe - Win32 Debug'.--------------------Configuration: TestExe - Win32 Debug--------------------Compiling resources...Compiling...StdAfx.cppCompiling...TestExe.cppTestExeDlg.cppGenerating Code...Linking...TestExeDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall CTest::CTest(void)"(__imp_??0CTest@@QAE@XZ)TestExeDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) int __cdecl fnTest(void)"(__imp_?fnTest@@YAHXZ)Debug/TestExe.exe : fatal error LNK1120: 2 unresolved externalsError executing link.exe.TestExe.exe - 3 error(s), 0 warning(s)
ステップ7
コンパイラDLL記号を教えてあげましたが、リンクはまだ分かりません.リンクに伝えなければなりませんProject|Settings|Linkを選択し、DLLのlibファイルをObject/library modulesに追加します:screen.width-500)this.style.width=screen.width-500;">----------------------------------------------
ステップ8
はい、コンパイルします.プログラムを実行する前に、Testを忘れないでください.dllはEXEのディレクトリにコピーします.
ステップ9
次に、OnInitDialog()関数にブレークポイントを入れて、ポイントGO(F 5)デバッグ運転を行います.
screen.width-500)this.style.width=screen.width-500;"> fnTestは42を返し、私たちの予測と同じであることがわかります.CTest類も同様の方法で試験することができる.
要点
VSのエンジニアリングウィザードはVC++DLLの作成に良いスタートを切った.
関数、クラス、変数はDLLから導出できる.
#defineプリプロセッサ定義を使用すると、1つのヘッダファイルをDLLとアプリケーションで共通に使用することができる.
DLLはその記号を導出し、アプリケーションはこのDLL記号をインポートする.アプリケーションをコンパイルするとき、コンパイラはヘッダファイルから見るDLL記号、アプリケーションをリンクするときはインポートライブラリ(Test.lib)からDLL記号を見る.
アプリケーションを実行する場合、DLLはEXEと同じディレクトリに配置する必要があります.DLLはwindowsやsystemディレクトリにも入れることができます.これも可能ですが、いくつかの問題を引き起こすことが多いので、を避けるべきです.
コメント:
また実際の仕事では、私は7歩目の方法をあまり使いません.このようにすると、大きな工事ではDLLやLibファイルの管理が困難になることが多い.libディレクトリとbinディレクトリを作成し、ここに使用するlibファイル、dllファイル、exeファイルをすべて入れたいと思います.もしそうすれば、リンクにlibファイルを見つけたことをどのように伝えますか?2つの方法があります.
1.Tools|Options|Directories and set Show directories forを「Library files」に選択する.私たちのプロジェクトで使用するLibファイルのパスを下に追加します.
screen.width-500)this.style.width=screen.width-500;">
  • 2. もう1つの方法は、Project|Settings|Linkを選択し、categoryをInputとし、下のAdditional library pathかごに工事で使用するlibファイルの所在経路を入力することである.screen.width-500)this.style.width=screen.width-500;">

  • どちらの方法がもっといいですか.これはあなたの開発環境にかかっています.第1の方法は、プロジェクト全体が共有するディレクトリパスの設定を要求し、すべての開発者に対するVSをこれらのパスに設定しなければならない.
    第2の方法は、各エンジニアリングが独自の経路をカスタマイズすることを可能にし、エンジニアリングに格納され、開発者のコンピュータに同じディレクトリが格納されている場合、各開発者はエンジニアリングに署名して設計することができる.これにより、各機器に同じ経路を設けることを回避することができる.
     
    今まで、私はどのように使用するLIBファイルを指定するかを言っていません.私の方法はDLLのTestです.hに2行追加すると、下のように見えます.
    #ifdef TEST_EXPORTS    #define TEST_API __declspec(dllexport)#else    #define TEST_API __declspec(dllimport)    #pragma message("automatic link to Test.lib")   // <== add this line    #pragma comment(lib, "Test.lib")                // <== add this line#endif// This class is exported from the Test.dllclass TEST_API CTest 
    {
    public:
        CTest(void);
    };

    extern TEST_API int nTest;

    TEST_API int fnTest(void);

    これにより、プロジェクトにDLLのヘッダファイルが含まれている場合、自動的にDLLのlibをリンクすることが保証され、VSのOUTPUTウィンドウからpragma messageが私たちに伝えた「automatic link to Test.lib」というメッセージを見ることができる.(PS:原文はこちらhttp://www.codeproject.com/dll/XDllPt1.aspdemoもここでダウンロードできます)