C#调用C++动态链接库之Win32dll(函数)、MFCdll(对话框)

        最近想把MFC写的对话框程序封装成.dll文件供C#程序调用,其中遇到了很多问题,现记录如下,以供参考!

一、在做MFC对话框封装之前顺带讲下函数的封装,这个相对简单。

1- 首先创建Win32 project,命名为mydll;


2- 应用类型选择DLL,完成;


3- 生成工程目录如下;


4- 在mydll.h头文件中添加代码如下(以实现add函数封装为例);

#include <string>

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport) 
#else
#define MYDLL_API __declspec(dllimport)
#endif

// This class is exported from the mydll.dll
class MYDLL_API Cmydll {
public:
	Cmydll(void);
	// TODO: add your methods here.
};
extern MYDLL_API int nmydll;
MYDLL_API int fnmydll(void);


//以上为编译器自动生成代码
//需要导出的函数必须添加 __declspec(dllexport),MYDLL_API前面已定义
extern "C" MYDLL_API int __stdcall add(int a,int b);

5- 在mydll.cpp中完成add函数实现; 

#include "stdafx.h"
#include "mydll.h"
#include <iostream>

using namespace std;
// This is an example of an exported variable
MYDLL_API int nmydll=0;

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

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

//以上为编译器自动生成代码
//add函数实现
MYDLL_API int __stdcall add(int a, int b)
{
	return a + b;
}
6- 编译生成dll文件;

7- 创建C#程序调用该dll文件;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;//必须添加此行
namespace usemydll
{
    class Program
    {
        //dll路径按实际情况填写,最好将dll文件复制粘贴到项目文件根目录中
        [DllImport(@"E:\Project_yuanmin\mydll\Debug\mydll.dll", EntryPoint = "add")]
        extern static int add(int a, int b);
        static void Main(string[] args)
        {
            int c = add(55,45);
            Console.WriteLine(c);
            Console.Read();
            
        }
    }
}
二、下面是封装MFC对话框过程,前提:我编译好了一个MFC对话框程序并调试成功,此处以一个tracker跟踪器项目为例

1- 创建MFC DLL项目,命名为trackerdll;


2- 选择Regular DLL;



3- 生成项目目录如下(将要封装的对话框对应的类头文件及实现文件复制粘贴到dll项目文件夹并导入项目目录,

此处为TrackerDlg.h和TrackerDlg.cpp两个文件)


6-导入对话框资源文件;


7- 在trackerdll.cpp文件中添加代码如下(需在相应头文件中添加#include "resource.h",确认导入对话框资源定义);

#include "stdafx.h"

#include "trackerdll.h"//添加必要头文件,使用了第三方dll的需将对应文件添加至项目文件夹中
#include "TrackerDlg.h"
#include "HCNetSDK.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//
//TODO: If this DLL is dynamically linked against the MFC DLLs,
//		any functions exported from this DLL which call into
//		MFC must have the AFX_MANAGE_STATE macro added at the
//		very beginning of the function.
//
//		For example:
//
//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
//		{
//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
//			// normal function body here
//		}
//
//		It is very important that this macro appear in each
//		function, prior to any calls into MFC.  This means that
//		it must appear as the first statement within the 
//		function, even before any object variable declarations
//		as their constructors may generate calls into the MFC
//		DLL.
//
//		Please see MFC Technical Notes 33 and 58 for additional
//		details.
//

// CtrackerdllApp

BEGIN_MESSAGE_MAP(CtrackerdllApp, CWinApp)
END_MESSAGE_MAP()


// CtrackerdllApp construction

CtrackerdllApp::CtrackerdllApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}


// The one and only CtrackerdllApp object

CtrackerdllApp theApp;


// CtrackerdllApp initialization

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

	return TRUE;
}

//以上除了include项均为编译器自动生成代码
//需要导出的函数在下面按要求编写,此处以显示对话框函数为例
#define TRACKER_API extern "C" _declspec(dllexport)

TRACKER_API void showDlg()//导出显示对话框函数
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());//使用了MFC控件
	
	NET_DVR_Init();//海康SDK初始化,此处为本项目单独要求,其他项目不需要添加
	
	TrackerDlg dlg;//显示对话框
	dlg.DoModal();

}

8- 在项目>>属性>>General中对应修改Use of MFC; Character set项,

项目>>属性>>C/C++>>Code Generation中对应修改Runtime Library;



9- 编译生成dll文件,并创建C#程序调用,代码如下;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;//必须添加此行
namespace usemydll
{
    class Program
    {
        //dll路径按实际情况填写,最好将dll文件复制粘贴到项目文件根目录中
        [DllImport(@"E:\Project_yuanmin\trackerdll\Debug\trackerdll.dll", EntryPoint = "showDlg")]
        extern static void showDlg();
        static void Main(string[] args)
        {
            showDlg();
            
        }
    }
}
ps:涉及多线程调试错误,参考: http://www.cnblogs.com/zwh0214/p/6048360.html

MFC的使用,有三种设置: 
 1.使用标准Windows库
 2.在静态库中使用MFC:是将DLL中的相关代码写进EXE文件中,文件较大,但是可以在没有相关DLL的机器上运行;
 3.在共享DLL中使用MFC:指的是打包时一些MFC的DLL的内容没有被包含在EXE文件中,所以EXE文件较小,但是运行时要求系统中要有相关的DLL文件;
多线程调试
/MD:在dll中使用多线程,创建动态链接库的release版本,需要选择。
/MT: 在exe里使用多线程,创建exe的release版本,需要选择。
/MTd:同/MT一样,不过是在Debug版本中使用。
/MDL:同/MD一样,不过是在Debug版本中使用。

如果是Debug的“在静态库中使用MFC”,不要使用MDd,改用MTd,然后编译即可通过。
如果是Debug的“在共享DLL中使用MFC”,注意不要使用MTd,改用MDd;
如果是Release版本“在静态库中使用MFC”,不要使用MD,使用MT;
如果是Release版本的“在共享DLL中使用MFC”,不要使用MT,使用MD。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值