创建非托管常规MFC DLL并从托管C ++ .NET应用程序调用时出现问题 [英] Problems creating a unmanaged regular MFC DLL and call it from an managed C++ .NET app

查看:89
本文介绍了创建非托管常规MFC DLL并从托管C ++ .NET应用程序调用时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对DLL有一些疑问.我尝试了很多,但无法获得完整的图片.大多数示例都在C#等中.

I have a few questions about DLL's. I tried a lot but I can not get the complete picture. Most examples are in C# etc.

使用VS2005中的向导,我创建了一个非托管的MFC常规DLL(由于存在剩余代码,因此必须为MFC).然后,我尝试将其导入VS2005管理的.NET C ++应用程序中.参见下面的代码.

With the wizard in VS2005 I created a unmanaged MFC regular DLL (must be MFC because of remaining code). Then I tried to import it in a VS2005 managed .NET C++ application. 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;
};

在应用程序中

[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且应用程序崩溃的情况下工作(错误:尝试读取或写入受保护的内存)?

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)?

2-在这种情况下,虽然我没有调用InitInstance(),但是否执行了它(为什么没有ExitInstance)?

2 - Is in this case the InitInstance() executed although I don't call it (and why is there no ExitInstance)?

3-为什么在使用DLLImport时会看到一些示例提供EntryPoint,而有些则没有?

3 - Why do I see some examples giving the EntryPoint when using DLLImport and some don't?

4-我可以给MFC C ++ DLL中的函数(而不是普通的函数指针)提供委托作为参数来创建回调吗?

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?

推荐答案

无法P/调用方法.如果要从非托管DLL导出类以在托管环境中使用,则必须将其展平,例如.

Methods cannot be P/Invoked. If you want to export a class from unmanaged DLL to be used in managed world, you have to flatten it, eg.

  • 创建一个构造函数,如下所示:

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

  • 在C#中准备P/调用的外部方法(您已经知道该怎么做,因此我将省略它们)

  • Prepare P/Invoked external methods in C# (You already know how to do it, so I'll omit these)

    创建您的类的实例:

    IntPtr instance = MyClass_Create();
    

    然后调用其方法:

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

    最后,销毁该类:

    MyClass_Destroy(instance);
    

  • 别忘了添加一些错误检查-为了使示例清晰易懂,我省略了它.

    Don't forget to add some error checking - I omitted it to keep the example clear.

    这篇关于创建非托管常规MFC DLL并从托管C ++ .NET应用程序调用时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆