DLL-正规的 DLL 共享MFC DLL
导出函数、类
实例1:
<注意:将此处两个函数封装到 Fun.h, Fun.cpp 中, 否则关联.exe调试时出错, 同实例3添加全局函数>
MFC DLL 导出函数
1). 创建一个 MFC dll 程序( DLLExm2 ), 选择 Regular DLL using shared MFC DLL
2). 添加两个函数
InsertOne: 不可以对外访问
InsertSort: 可以对外访问
void InsertOne(int _eArr[], int _nStCnt, int _e)
{
// 从这个有序序列的最后一个元素开始
for(int j=_nStCnt-1; j>=0; --j)
{
if(_eArr[j] > _e)
{
_eArr[j+1] = _eArr[j]; // 往后移
}
else
{
break;
}
}
_eArr[j+1] = _e; // 将该元素放置正确位置上
}
_declspec(dllexport) void InsertSort(int _eArr[], int _nCnt)
{
// 从 第二个开始,把他们依次插入到有序的序列中去
for(int i=1; i<_nCnt; ++i)
{
InsertOne(_eArr, i, _eArr[i]);
}
}
3). 编译
4). 创建一个单文档程序, 使用DLL (mfc程序使用)
5). 重写 OnDraw 函数, 添加声明
void InsertSort(int _eArr[], int _nCnt)
void CCM21_DllTestDocView::OnDraw(CDC* pDC)
{
CCM21_DllTestDocDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int arr_nNum[5] = {10, 20, 6, 18, 12};
InsertSort(arr_nNum, 5);
CString str;
str.Format("%d, %d, %d, %d, %d", arr_nNum[0],
arr_nNum[1],arr_nNum[2],arr_nNum[3],arr_nNum[4]);
pDC->TextOut(0, 0, str);
}
6). 隐式加载方式 加载 DLLExm2.lib
拷贝 DLLExm2.dll, DLLExm2.lib 到目录下
7). C++程序也可以使用, 步骤同上 (c语言不能直接使用)
(
C语言参见:
#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif
)
实例2:
导出类
1). 添加类 CPerson ( Insert->New class )
2). 导出类
在类名和class之间加VC的关键字 _declspec(dllexport)
3). 单文档类使用 导出类
拷贝头文件到目录下
1> 添加头文件 Person.h
2> 使用即可
Person p;
实例3:
添加全局函数 ( .h, .cpp 文件 )
1). 添加导出的全局函数
Fun.h
_declspec(dllexport) void a();
_declspec(dllexport) void b();
Fun.cpp
#include "stdafx.h" // 注意此行include必须添加到第一行
#include "Fun.h"
void a()
{
}
void b()
{
}
2). 使用全局函数
方式1:
只添加头文件即可
#include "Fun.h"
方式2:
只添加函数声明即可
void a();
void b();
实例4:
dll 直接可以互相使用
步骤:
1). 建立 dll 项目 DllInner, 添加类 CMyClass
class _declspec(dllexport) CMyClass
{
public:
CMyClass();
virtual ~CMyClass();
int GetData();
};
// .cpp
CMyClass::CMyClass()
{
}
CMyClass::~CMyClass()
{
}
int CMyClass::GetData()
{
return 1000;
}
2). 建立第二个dll项目 DllSmd, 添加类 CPerson, 并使用 CMyClass 类
1> 编写CPerson
class _declspec(dllexport) CPerson
{
public:
CPerson();
virtual ~CPerson();
int Fun();
};
//.cpp
#include "MyClass.h"
CPerson::CPerson()
{
}
CPerson::~CPerson()
{
}
int CPerson::Fun()
{
CMyClass myClass;
return myClass.GetData();
}
2> 添加dll文件
Setting -> DllInner.lib
3> 拷贝 MyClass.h, DllInner.dll, DllInner.lib 到当前目录
3). 建立测试程序使用 dll项目 DllSmd (c++)
1> 添加Setting -> DllSmd.lib
2> #include "Person.h"
3> 将 DllSmd.lib, DllSmd.dll, DllInner.dll, DllInner.lib 拷贝到当前目录
4). 运行测试程序
========
隐式加载方式
方式二:
在stdafx.h文件中添加代码:
#pragma comment(lib,”M21_DllExm.lib”)
注意: 将.lib文件放到当前目录下
Win32下的
(1)Win32 DLL 完成 DLL 导出两个函数.txt
实例:
Win32 DLL 完成 DLL 导出两个函数 ( MFC,C++程序均可以使用, C程序不能使用 )
1. 建立一个 DLL 文件
new -> project -> Win32 DLL -> DLLTest
2. 建立一个空项目
3. 添加一个 dll1.cpp, 编写两个函数
_declspec(dllexport) int Add(int x,int y)
{
return x+y;
}
_declspec(dllexport) int Subtract(int x,int y)
{
return x-y;
}
4. 编译
5. 查看 dll 文件中包含的信息
C:\Program Files\Microsoft Visual Studio\VC98\Bin\下找到VCVARS32.bat 命令行运行
cd Debug
dumpbin -exports dll1.dll
6. 建立测试程序 DLLTestDLg, 基于对话框程序
7. 放置两个按钮add, aubtract, 调用两个函数
void CDLLTestDLg::OnBtnAdd()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("3+5=%d",Add(3,5));
MessageBox(str);
}
void CDLLTestDLg::OnBtnSubtract()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("5-3=%d",Subtract(5,3));
MessageBox(str);
}
8. 添加函数声明
extern int Add(int x,int y);
extern int Subtract(int x,int y);
可以使用标示符表示这两个函数是从动态链接库的.lib文件引用的,以生成效率更高的代码
_declspec(dllimport) int Add(int x,int y);
_declspec(dllimport) int Subtract(int x,int y);
9. 设置隐式调用
Project->Setting->Link->Object/Library Modules -> DLLTest.lib
10. 拷贝 Dll1.lib和Dll1.dll 拷贝到当前目录下
如果要查看 DllTest.exe 文件信息,使用命令行 dumpbin -imports dlltest.exe
-------------
添加.h头文件
11. 修改 DLL 项目, 添加 dll1.h, 在其中添加 函数声明, 用一组宏来取代_declspec(dllimport)
dll1.h:
#ifdef DLL1_API
#else
#define DLL1_API extern "C" _declspec(dllimport)
#endif
DLL1_API int _stdcall Add(int a,int b);
DLL1_API int _stdcall Subtract(int a,int b);
dll1.cpp
#define DLL1_API extern "C" _declspec(dllexport)
#include "Dll1.h"
#include <Windows.h>
#include <stdio.h>
int _stdcall Add(int a,int b)
{
return a+b;
}
int _stdcall Subtract(int a,int b)
{
return a-b;
}
12. 修改对话框程序
1> 删除函数声明
2> 添加头文件
#include "dll1.h"
-------------
编写一个C++程序, 也可以使用上述函数
(2)Win32 DLL 完成 DLL 导出两个函数-C语言.txt
在 Visual C++ 中,工作空间(workspaces)和项目(projects)不同。
项目通常与建立的应用程序(.exe)或者动态链接库(.dll)相联系。一个工作空间可以包含一个或多个项目。
实例:
建立DLL, 建立测试程序 (WIN32 DLL) (mfc,c/c++均可以使用)
1). 新建 Workspace
File -> New -> Workspaces -> 输入Workspace Name (Li9_1)
2). 在 Workspace 下新建项目
File -> New -> Projects -> Win32 Dynamic-Link Library
-> 选中单选按钮Add To Current Workspace
-> Project Name (Li9_1Lib)
-> Location 栏删除Li9_1Lib子目录以便项目建立在Li9_1 目录
-> An Empty DLL Project
3). 添加文件
Li9_1Lib.h
/*-----------------------------------------
Li9_1Lib.h header file
------------------------------------------*/
#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif
EXPORT int Add(int x, int y);
Li9_1Lib.c
/*---------------------------------------
Li9_1Lib.c
-----------------------------------------*/
#include <windows.h>
#include "Li9_1Lib.h"
int WINAPI DllMain ( HINSTANCE hInstance, DWORD fdwReason, PVOID
pvReserved)
{ return TRUE ; }
EXPORT int Add(int x, int y)
{ return (x+y); }
Release 或按 Debug, 建立Li9_1Lib.dll
Li9_1Lib.lib(动态链接库的引用库), Li9_1Lib.dll(动态链接本身)
这两个文件中定义了 EXPORT 宏。
DLL 中应用程序使用的函数必须是输出(exported)的。即确保函数名添加到Li9_1Lib.lib 库中(以便链接程序在链接使用此函数的应用程序时,能够解析出函数名称),而且该函数在Li9_1Lib.dll 中也是找得到的
4). 建立测试程序 ( 在mfc程序中使用 )
在工作空间 Li9_1 中建立第二个项目Li9_1Test,并且该项目使用Li9_1Lib.dll 文件导出的函数
File -> New -> Projects -> MFC AppWizard(exe)
-> Add To Current Workspace
-> Li9_1Test ( 再在Locations 栏删除Li9_1Test 子目录 )
-> Dialog based -> Finish
5). 添加按钮
IDC_BNT_Add "Add"
void CLi9_1TestDlg::OnBNTAdd()
{
int x=5,y=3;
CString str;
str.Format("%d",Add(x,y));
AfxMessageBox(str);
}
5). 在 Dlg.h 中引入 dll
// CLi9_1TestDlg dialog
#ifdef __cplusplus
#define IMPORT extern "C" __declspec (dllimport)
#else
#define IMPORT __declspec (dllimport)
#endif
IMPORT int Add(int x, int y);
class CLi9_1TestDlg : public CDialog
{ …}
6). 设置 Project -> Settings 选项
1). General, ,确保项目Li9_1Lib 和项目Li9_1Test 编译生成的中间文件(Intermediate files)和最终输出文件(Output files)在同一个目录下。
D:\C++_Test\Li9_1
2). Project -> Dependencies
使项目Li9_1Test 依赖项目Li9_1Lib 的输出
7). 运行程序