一、DLL编写及导出
DLL中导出函数有两种方法,一种是通过在函数声明前面加上__declspec(dllexport)的修饰符;另一种是通过.def文件来说明导出的函数。我们先看第一种方法。
第一种DLL导出函数的方法:
我们先创建工程,选择Win32 Dynamic-Link Library,如下图:
创建一个简单的DLL工程,如下图:
点确定,如下图:
得到工程如下:
然后我们在Header files中添加一个TestDLL.h的头文件,然后在TestDLL.h中和TestDLL.cpp中编写函数:
TestDLL.h:
#ifndef __TESTDLL_H__
#define __TESTDLL_H__
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void Swap(int* a, int* b);
__declspec(dllexport) int Max(int a, int b);
__declspec(dllexport) int Min(int a, int b);
#ifdef __cplusplus
}
#endif
#endif//__TESTDLL_H__
这里在头文件的函数声明前面加上了__declspec(dllexport)修饰符,在编译的时候编译器就会识别该修饰符并导出相应的函数。
注意这里在函数的声明前加上了extern "C",如果不加上extern "C"那么编译器在编译链接函数的会对函数名称进行名称重整(name mangling),那么导出的函数就不再是原来的函数名了。
TestDLL.cpp
// TestDLL.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "TestDLL.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
void Swap(int* a, int* b)
{
*a += *b;
*b = *a - *b;
*a = *a - *b;
}
int Max(int a, int b)
{
return (a>b ? a : b);
}
int Min(int a, int b)
{
return (a>b ? b : a);
}
然后编译工程即可在工程目录下面找到DLL文件,如下图:
这里我们可以通过VC6的工具Depends查看DLL文件查看导出来的函数,如下图:
通过Depends可以看到我们通过DLL导出了三个函数,函数名分别是Max、Min、Swap。
这里可以看到三个函数的函数名仍然是代码里面写的函数名,就是因为前面提到的加了extern "C"。
如果去掉extern "C"我们可以试试看会得到什么样的函数名:
可以看到函数名就变了,前后加了一堆乱码一样的东西。
其实这里是因为是C++的工程,C++是支持函数重载的,如果只通过函数名来导出函数一旦碰到函数重载的情况的话就会产生二义性,所以添加extern "C"来告诉编译器按C标准来编译链接这些函数。
第二种DLL导出函数的方法:
还是刚刚那个工程,我们把函数声明前面的__declspec(dllexport)修饰符去掉。然后新建一个.def文件在Source Files中。
.def文件的格式如下:
LIBRARY CMPNT2 -->dll名称
LIBRARY CMPNT2 -->dll名称
EXPORTS -------->导出函数的标记符
Dll_Function_1 -->被导出的函数名称
Dll_Function_2
..................
然后我们再次编译同样可以得到导出了三个函数的DLL文件
到这里就介绍完了两种DLL导出函数的方法。