3

DLL についていくつか質問があります。いろいろ試しましたが、全体像がつかめません。ほとんどの例は C# などにあります。

VS2005 のウィザードを使用して、アンマネージ MFC の通常の DLL を作成しました (コードが残っているため、MFC でなければなりません)。次に、VS2005 マネージド .NET C++ アプリケーションにインポートしようとしました。以下のコードを参照してください。

mfc_main.h:

//---------------------------------------------------------
// mfc_main.h : main header file for the mfc_main DLL
//---------------------------------------------------------

#pragma once

#ifndef __AFXWIN_H__
    #error "include 'stdafx.h' before including this file for PCH"
#endif

#include "resource.h"       // main symbols

class __declspec(dllexport) Cmfc_mainApp : public CWinApp
{
public:
    Cmfc_mainApp();

// Overrides
public:
    virtual BOOL InitInstance();

    int SayHello(int j);

    int init;
    DECLARE_MESSAGE_MAP()
};

mfc_main.cpp:

//----------------------------------------------------------------
// mfc_main.cpp : Defines the initialization routines for the DLL.
//----------------------------------------------------------------

#include "stdafx.h"
#include "mfc_main.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

BEGIN_MESSAGE_MAP(Cmfc_mainApp, CWinApp)
END_MESSAGE_MAP()

Cmfc_mainApp::Cmfc_mainApp()
{
}

Cmfc_mainApp theApp;

BOOL Cmfc_mainApp::InitInstance()
{
    CWinApp::InitInstance();

    return TRUE;
}

int Cmfc_mainApp::SayHello(int j)
{
    init = 12;  // Comment this out the application works !!!!

    return j * 6;
};

適用中

[DllImport("mfc_main.dll",
      EntryPoint    = "?SayHello@Cmfc_mainApp@@QAEHH@Z",
      ExactSpelling = true)]
static int SayHello(int a);

......

private: System::Void button_Click(System::Object^ sender, System::EventArgs^ e) 
     {
         int retval = SayHello(2);
     }

私の質問は次のとおりです。

1 - 関数 SayHello で init = 12 がなくても動作し、アプリケーションがクラッシュするのはなぜですか (エラー: 保護されたメモリを読み書きしようとしました)?

2 - この場合、InitInstance() は呼び出されていませんが実行されていますか (なぜ ExitInstance がないのですか)。

3 - DLLImport の使用時に EntryPoint を与える例とそうでない例があるのはなぜですか?

4 - コールバックを作成するために、通常の関数ポインターの代わりに、MFC C++ DLL の関数へのパラメーターとしてデリゲートを与えることはできますか?

4

1 に答える 1

0

メソッドは P/Invoked できません。アンマネージド DLL からクラスをマネージド ワールドで使用するためにエクスポートする場合は、フラット化する必要があります。

  • 次のようなコンストラクタ関数を作成します。

    __declspec(dllexport) void * __stdcall MyClass_Create()
    {
         return new MyClass();
    }
    
  • 次のようなデストラクタ関数を作成します。

    __declspec(dllexport) void * __stdcall MyClass_Destroy(MyClass * instance)
    {
         delete instance;
    }
    
  • メソッド呼び出しをフラット化します。クラスに次のメソッドがあるとします。

    int MyClass::MyMethod(int i, double j) { ... }
    

    次に、次の関数を作成する必要があります。

    __declspec(dllexport) int __stdcall MyClass_MyMethod(MyClass * instance, int i, double j)
    {
        return instance->MyMethod(i, j);
    }
    
  • C#でP/Invokedの外部メソッドを用意する(やり方はもうお分かりなので割愛します)

  • クラスのインスタンスを作成します。

    IntPtr instance = MyClass_Create();
    

    次に、そのメソッドを呼び出します。

    int i = MyClass_MyMethod(instance, 4, 2.0);
    

    最後に、クラスを破棄します。

    MyClass_Destroy(instance);
    

エラー チェックを追加することを忘れないでください。例をわかりやすくするために省略しました。

于 2013-03-08T10:28:05.053 に答える