简体   繁体   English

创建非托管常规MFC DLL并从托管C ++ .NET应用程序调用它时出现问题

[英]Problems creating a unmanaged regular MFC DLL and call it from an managed C++ .NET app

I have a few questions about DLL's. 我有一些关于DLL的问题。 I tried a lot but I can not get the complete picture. 我尝试了很多,但我无法得到完整的图片。 Most examples are in C# etc. 大多数例子都在C#等。

With the wizard in VS2005 I created a unmanaged MFC regular DLL (must be MFC because of remaining code). 使用VS2005中的向导,我创建了一个非托管MFC常规DLL(由于剩余代码,必须是MFC)。 Then I tried to import it in a VS2005 managed .NET C++ application. 然后我尝试在VS2005托管的.NET C ++应用程序中导入它。 See code below. 见下面的代码。

mfc_main.h: 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:

//----------------------------------------------------------------
// 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;
};

in application 在申请中

[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);
     }

My questions are: 我的问题是:

1 - Why is it working without the init = 12 in the function SayHello and with the application crashes (error: Attempted to read or write protected memory)? 1 - 为什么在SayHello函数中没有init = 12并且应用程序崩溃(错误:尝试读取或写入受保护的内存)时它是否正常工作?

2 - Is in this case the InitInstance() executed although I don't call it (and why is there no ExitInstance)? 2 - 在这种情况下执行InitInstance()虽然我没有调用它(为什么没有ExitInstance)?

3 - Why do I see some examples giving the EntryPoint when using DLLImport and some don't? 3 - 为什么我在使用DLLImport时看到一些给出EntryPoint的例子,有些则没有?

4 - Can I give a delegate as parameter to a function in a MFC C++ DLL instead of a normal function pointer, to create a callback? 4 - 我可以将委托作为参数提供给MFC C ++ DLL中的函数而不是普通函数指针,以创建回调吗?

Methods cannot be P/Invoked. 方法不能被P / Invoked。 If you want to export a class from unmanaged DLL to be used in managed world, you have to flatten it, eg. 如果要从非托管DLL导出类以在托管环境中使用,则必须将其展平,例如。

  • Create a constructor function, which looks like: 创建一个构造函数,如下所示:

     __declspec(dllexport) void * __stdcall MyClass_Create() { return new MyClass(); } 
  • Create a destructor function, which looks like: 创建一个析构函数,如下所示:

     __declspec(dllexport) void * __stdcall MyClass_Destroy(MyClass * instance) { delete instance; } 
  • Flatten method calls. 展平方法调用。 Let's suppose, that you have the following method in your class: 我们假设您在班级中有以下方法:

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

    Then you have to create a following function: 然后你必须创建一个以下功能:

     __declspec(dllexport) int __stdcall MyClass_MyMethod(MyClass * instance, int i, double j) { return instance->MyMethod(i, j); } 
  • Prepare P/Invoked external methods in C# (You already know how to do it, so I'll omit these) 在C#中准备P / Invoked外部方法(你已经知道如何去做了,所以我省略了这些)

  • Create instance of your class: 创建类的实例:

     IntPtr instance = MyClass_Create(); 

    Then call its method: 然后调用它的方法:

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

    Finally, destroy the class: 最后,破坏班级:

     MyClass_Destroy(instance); 

Don't forget to add some error checking - I omitted it to keep the example clear. 不要忘记添加一些错误检查 - 我省略它以保持示例清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM