方法一
1 (vc6.0)创建一个空的动态链接库工程,在工程中添加dll_1.cpp文件
在dll_1.cpp文件中输入如下代码,让后编译,在debug目录
下回生成dll_1.dll和dll_1.lib文件
#define EXPORT __declspec(dllexport)
EXPORT int add(int a, int b)
{
return (a+b);
}
EXPORT int sub(int a, int b)
{
return (a-b);
}
2 创建一个MFC测试工程,测试工程代码如下,然后把
dll_1.dll和dll_1.lib文件拷贝到该工程下(vc的dependency工具查看.exe文件的dll)
#pragma comment(lib, "dll_1") //加入动态链接库的引入库文件
extern int add(int a, int b);
extern int sub(int a, int b);
// 以上2行也可以改为一下方式
// __declspec(dllimport) int add(int a, int b);
// __declspec(dllimport) int sub(int a, int b);
void CTestDllDlg::OnAdd()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("1+2= %d", add(1,2));
MessageBox(str, NULL);
}
void CTestDllDlg::OnSub()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("3-2= %d", sub(3,2));
MessageBox(str, NULL);
}
方法二(dll中导出C++类)
1 编写dll文件
// dll_1.h
#define DLL_EXPORT_CLASS __declspec(dllexport)
#define DLL_IMPORT_CLASS __declspec(dllexport)
#include <stdio.h>
#include <windows.h>
class DLL_EXPORT_CLASS Point
{
public:
void OutPutPoint(int x, int y);
};
//dll_1.cpp
#include "dll_1.h"
void Point::OutPutPoint(int x, int y)
{
HWND hWnd = GetForegroundWindow();
HDC hDc = GetDC(hWnd);
char buf[20];
sprintf(buf, "x=%d, y=%d",x,y);
TextOut(hDc, 0, 0, buf, strlen(buf));
ReleaseDC(hWnd, hDc);
}
2 在测试工程下(把编译好的dll_1.dll和dll_1.lib拷贝到该工程下)
测试代码如下
#include "dll_1.h"
#pragma comment(lib, "dll_1") //加入动态链接库的引入库文件
void CTestDllDlg::OnDllClass()
{
// TODO: Add your control notification handler code here
Point pt;
pt.OutPutPoint(1,2); //在对话框上画点1 2
}
3 方法三(只导出类中部分函数)
1 编写dll文件
// dll_1.h
#define DLL_EXPORT_CLASS __declspec(dllexport)
#define DLL_IMPORT_CLASS __declspec(dllexport)
#include <stdio.h>
#include <windows.h>
class Point
{
public:
// 只导出类中部分函数
void DLL_EXPORT_CLASS OutPutPoint(int x, int y);
void DoNotExport(void);
};
//dll_1.cpp
#include "dll_1.h"
void Point::OutPutPoint(int x, int y)
{
HWND hWnd = GetForegroundWindow();
HDC hDc = GetDC(hWnd);
char buf[20];
sprintf(buf, "x=%d, y=%d",x,y);
TextOut(hDc, 0, 0, buf, strlen(buf));
ReleaseDC(hWnd, hDc);
}
void Point::DoNotExport(void)
{
}
2 在测试工程下(把编译好的dll_1.dll和dll_1.lib拷贝到该工程下)
测试代码如下
#include "dll_1.h"
#pragma comment(lib, "dll_1") //加入动态链接库的引入库文件
void CTestDllDlg::OnDllClass()
{
// TODO: Add your control notification handler code here
Point pt;
pt.OutPutPoint(1,2); //在对话框上画点1 2
}
方法四(解决名字改编问题和调用约定)
(添加 extern "C"和_stdcall)
1 (vc6.0)创建一个空的动态链接库工程,在工程中添加dll_1.cpp文件
在dll_1.cpp文件中输入如下代码,让后编译,在debug目录
下回生成dll_1.dll和dll_1.lib文件
#define EXPORT extern "C" _declspec(dllexport)
EXPORT int _stdcall add(int a, int b)
{
return (a+b);
}
EXPORT int _stdcall sub(int a, int b)
{
return (a-b);
}
2 创建一个MFC测试工程,测试工程代码如下,然后把
dll_1.dll和dll_1.lib文件拷贝到该工程下(vc的dependency工具查看.exe文件的dll)
#pragma comment(lib, "dll_1") //加入动态链接库的引入库文件
extern int _stdcall add(int a, int b); //编译在库中_add@8 ---有2个int才参数共占8字节
extern int _stdcall sub(int a, int b); //编译在库中_sub@8 ---有2个int才参数共占8字节
// 以上2行也可以改为一下方式
// __declspec(dllimport) int _stdcall add(int a, int b);
// __declspec(dllimport) int _stdcall sub(int a, int b);
void CTestDllDlg::OnAdd()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("1+2= %d", add(1,2));
MessageBox(str, NULL);
}
void CTestDllDlg::OnSub()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("3-2= %d", sub(3,2));
MessageBox(str, NULL);
}
方法五
所以引入模块定义(DEF)文件来解决名字改变问题
1 (vc6.0)创建一个空的动态链接库工程,在工程中添加dll_1.cpp文件
在dll_1.cpp文件中输入如下代码。
int add(int a, int b)
{
return (a+b);
}
int sub(int a, int b)
{
return (a-b);
}
2 在上述工程中添加一个dll_1.def文件,在dll_1.def文件中添加
然后编译,在debug目录下回生成dll_1.dll和dll_1.lib文件
LIBRARY
EXPORTS
add
sub
3 创建一个MFC测试工程,测试工程代码如下,然后把
dll_1.dll和dll_1.lib文件拷贝到该工程下(vc的dependency工具查看.exe文件的dll)
#pragma comment(lib, "dll_1") //加入动态链接库的引入库文件
extern int add(int a, int b); //编译在库中add(用dependency查看dll1_1.dll)
extern int sub(int a, int b); //编译在库中sub
// 以上2行也可以改为一下方式
// __declspec(dllimport) int add(int a, int b);
// __declspec(dllimport) int sub(int a, int b);
void CTestDllDlg::OnAdd()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("1+2= %d", add(1,2));
MessageBox(str, NULL);
}
void CTestDllDlg::OnSub()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("3-2= %d", sub(3,2));
MessageBox(str, NULL);
}
-------------------------------------------
其实方法五产生的结果和c语言的约定调用方式生成的dll是一样的
(用dependency查看dll1_1.dll)即如下所示
#define EXPORT extern "C" _declspec(dllexport)
EXPORT int add(int a, int b)
{
return (a+b);
}
EXPORT int sub(int a, int b)
{
return (a-b);
}
//#pragma comment(lib, "dll_1")
// extern int add(int a, int b);
// extern int sub(int a, int b);
//
//__declspec(dllimport) int add(int a, int b);
//__declspec(dllimport) int sub(int a, int b);
void CTestDllDlg::OnAdd()
{
// TODO: Add your control notification handler code here
HINSTANCE hInc = LoadLibrary("dll_1.dll");
typedef int(*ADDPROC)(int, int);
ADDPROC add = (ADDPROC)GetProcAddress(hInc, "add");
if (!add)
{
MessageBox("获取函数地址失败");
return;
}
CString str;
str.Format("1+2= %d", add(1,2));
MessageBox(str, NULL);
}
=====================================================================
显示加载方式加载dll,调用动态链接库中的函数都是隐式静态调用方式进行的
下面几行注释掉
//#pragma comment(lib, "dll_1")
// extern int add(int a, int b);
// extern int sub(int a, int b);
//
//__declspec(dllimport) int add(int a, int b);
//__declspec(dllimport) int sub(int a, int b);
void CTestDllDlg::OnAdd()
{
// TODO: Add your control notification handler code here
HINSTANCE hInc = LoadLibrary("dll_1.dll");
typedef int(*ADDPROC)(int, int);
ADDPROC add = (ADDPROC)GetProcAddress(hInc, "add");
if (!add)
{
MessageBox("获取函数地址失败");
return;
}
CString str;
str.Format("1+2= %d", add(1,2));
MessageBox(str, NULL);
}