dll 编程的几种方法总结

本文总结了五种DLL编程的方法,包括导出C函数、导出C++类、只导出类的部分函数、解决名字改编问题和调用约定,以及使用DEF文件导出函数。详细介绍了每种方法的实现步骤和注意事项,适用于VC6.0环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一

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);
}




                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值