使用工具: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 项目的调用约定可以在属性里查看和修改,如下所示:
版权声明:本文为qq_29331365原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。