MFC学习笔记(一):动态库的创建,以及调用

使用工具:VS2012

一、创建一个 MFC DLL 项目:

选择 “带静态链接 MFC 的规则 DLL”:

我使用的 字符集 为 多字节(默认为 unicode,看个人喜好选择):

在 MFCLibrary1.h 头文件中 声明接口:

// MFCLibrary1.h : MFCLibrary1 DLL 的主头文件
//

#pragma once

#ifndef __AFXWIN_H__
	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h"		// 主符号


// CMFCLibrary1App
// 有关此类实现的信息,请参阅 MFCLibrary1.cpp
//

class CMFCLibrary1App : public CWinApp
{
public:
	CMFCLibrary1App();

// 重写
public:
	virtual BOOL InitInstance();

	DECLARE_MESSAGE_MAP()
};


/*
动态库中接口的声明:
	inData:传入参数;
	outData:传出参数;
	成功返回 0,失败返回 -1;
*/
extern "C" _declspec (dllexport) int GetString(char* inData, char* outData);

/*
动态库中接口的声明:
	inData:传入参数;
	返回 BSTR 类型数据;
*/
extern "C" _declspec (dllexport) BSTR GetBSTR(char* inData);

在 MFCLibrary1.cpp 源文件中写接口的实现:

// MFCLibrary1.cpp : 定义 DLL 的初始化例程。
//

#include "stdafx.h"
#include "MFCLibrary1.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//
//TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,
//		则从此 DLL 导出的任何调入
//		MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到
//		该函数的最前面。
//
//		例如:
//
//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
//		{
//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
//			// 此处为普通函数体
//		}
//
//		此宏先于任何 MFC 调用
//		出现在每个函数中十分重要。这意味着
//		它必须作为函数中的第一个语句
//		出现,甚至先于所有对象变量声明,
//		这是因为它们的构造函数可能生成 MFC
//		DLL 调用。
//
//		有关其他详细信息,
//		请参阅 MFC 技术说明 33 和 58。
//

// CMFCLibrary1App

BEGIN_MESSAGE_MAP(CMFCLibrary1App, CWinApp)
END_MESSAGE_MAP()


// CMFCLibrary1App 构造

CMFCLibrary1App::CMFCLibrary1App()
{
	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CMFCLibrary1App 对象

CMFCLibrary1App theApp;


// CMFCLibrary1App 初始化

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

	return TRUE;
}




/*
动态库中接口的实现:
	inData:传入参数
	outData:传出参数
*/
int GetString(char* inData, char* outData)
{
	// 将 char* 类型转换成 CString 类型
	CString str = CString(inData);
	// 获取字符串的长度
	int len = str.GetLength();
	if (len <= 0)
	{
		strcpy(outData, "传入参数为空!");
		return -1;
	}
	else
	{
		strcpy(outData, "传入参数为:" + str);
		return 0;
	}
}

/*
动态库中接口的实现:
	inData:传入参数
	返回 BSTR 类型数据
*/
BSTR GetBSTR(char* inData)
{
	// 获取传入数据的长度
	int len = strlen(inData);
	if (len <= 0)
	{
		// 将字符串转换成 BSTR 类型
		BSTR bstrText  = SysAllocString(L"传入参数为空!");	

		return bstrText;
	}
	else
	{
		CString str = "传入参数为:" + CString(inData);

		// 将字符串转换成 BSTR 类型
		BSTR bstrText  = str.AllocSysString();				
		
		return bstrText;
	}
}

注意:编译的时候会报如下错误:

原因就像错误信息所说的,因为我使用了 strcpy 这个函数,而这个函数是不安全的;

解决办法错误信息也说了,使用 strcpy_s 代替 strcpy,或者使用 _CRT_SECURE_NO_WARNINGS 宏定义;

我这里使用第二种方法:在 stdafx.h 中加宏定义,表示 忽略安全警告;如下所示:

编译成功后生成的文件如下:

其中 MFCLibrary1.dll 为动态链接库文件,MFCLibrary1.lib 为静态链接库文件;

如果是 动态调用链接库文件,只需要一个 MFCLibrary1.dll 文件就可以了;

如果是 静态调用链接库文件,除了要有 MFCLibrary1.dll 文件,还要有 MFCLibrary1.lib 和 MFCLibrary1.h 文件;

使用 depends.exe 工具查看动态库中的接口方法为:

 

 

二、创建一个 MFC 应用程序 项目,测试静态调用链接库:

注意:MFC 应用程序项目 和 MFC DLL 项目在 同一个解决方案下面。

选择 应用程序类型 为 基于对话框:

选择 生成的类 为 Dlg 结尾的;其他的不用改,直接 下一步 跳过;

在 Demo1Dlg.cpp 文件中包含 DLL 项目的头文件,并且链接 静态库文件(.lib):

注意:静态调用链接库,必须要有 MFCLibrary1.dll 、MFCLibrary1.lib、MFCLibrary1.h 三个文件:

这样,就可以在 MFC 应用程序项目中 调用 链接库里的方法了:

 

三、动态调用链接库(还是使用上面创建的 MFC 应用程序项目):

注意:定义函数指针的时候,有一个 __cdecl 表示调用约定,如果约定和动态库生成时使用的约定不一致,就会报错;

MFC DLL 项目的调用约定可以在属性里查看和修改,如下所示:

 

 

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值