样例1:无.def
./maths.h
./maths.cpp
文件->新建->项目->visual c++->win32->win32控制台应用程序(win32项目也可以)
填写项目名称MyDLL->确定->下一步->DLL->完成。
-
//maths.h
-
__declspec(dllexport) int add(int a, int b);
-
-
-
-
-
//maths.cpp
-
#include "dll.h"
-
-
-
__declspec(dllexport) int add(int a, int b)
-
{
-
return a+b;
-
}
.h和.cpp文件导出时都要加__declspec(dllexport),否则编译出错
没有dllmain.cpp,则提示没有入口点
样例2: 有.def
./maths.h
./maths.cpp
./maths.def
-
//maths.def
-
LIBRARY DLL
-
EXPORTS
-
add
-
-
-
//maths.h
-
int add(int a, int b);
-
-
-
//maths.cpp
-
#include "dll.h"
-
-
-
int add(int a, int b)
-
{
-
return a+b;
-
}
没有__declspec(dllexport)
增加.def
注意的几点:
1) .def不是必须的,可以使用__declspec(dllexport)代替
2) __declspec(dllexport)关键字导出 DLL 的函数
3) 模块定义 (.def) 文件是包含一个或多个描述 DLL 各种属性的 Module 语句的文本文件
4).def实例(使用 DEF 文件从 DLL 导出, (v=VS.80).aspx)
LIBRARY BTREE 文件中的第一个语句必须是 LIBRARY 语句。此语句将 .def 文件标识为属于 DLL。LIBRARY 语句的后面是 DLL 的名称。
EXPORTS EXPORTS 语句列出名称,可能的话还会列出 DLL 导出函数的序号值。通过在函数名的后面加上 @ 符和一个数字,给函数分配序号值。当指定序号值时,序号值的范围必须是从 1 到 N,其中 N 是 DLL 导出函数的个数。
Insert @1
Delete @2
5)动态链接库的应用基础
调用约定(Calling convention)决定:函数参数的压栈顺序,由调用者还是被调用者把参数弹出栈,以及产生函数修饰名的方法。编程调用DLL时,要注意调用约定的一致。
调用约定包括:
__cdecl
MFC默认调用约定。按从右至左的顺序压参数入栈,有调用者把参数弹出栈。对于C函数,__cdecl方式的名字修饰约定是在函数名称前添加一个下划线,对于C++函数使用不同的名字修饰方式。
__stdcall
所有的Win32 API函数都遵循该约定。按从右至左的顺序压参数入栈,由被调用者把参数弹出栈。对于C函数,__stdcall的名称修饰方式是在函数名字前添加下划线,在函数名字后添加@和函数参数的大小。
__fastcall
头两个DWORD类型或者占更少字节的参数被放入ECX和EDX寄存器,其他剩下的参数按从右到左的顺序压入栈。由被调用者把参数弹出栈。编译器使用两个@修饰函数名字,后跟十进制数表示的函数参数列表大小。
thiscall
仅仅应用与C++成员函数。This指针存放于CX寄存器,参数从右到左压栈。Thiscall不是C++的关键字,不能使用thiscall声明函数,它只能由编译器使用。
naked call
采用上述调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。Naked call不产生这样的代码。Naked call不是类型修饰符,因此必须和__declspec共同使用。
Windows编程中常见的集中函数类型声明宏都与__stdcall和__cdecl有关:
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
6)
(1). Dependencies (推荐使用,要求有lib源代码)
一个项目被分成多个工程来做,一个主工程exe,其他为静态库lib
Project-->dependencies,设置主工程的依赖为其他静态库lib
这时,主工程的Resource Files中自动添加了lib
在主工程中需要用到其他库的位置加入库的头文件
(2). 直接将lib添加到需要用的工程中(不太推荐,lib没能统一管理)
提供了lib和其头文件
选择工程-->右键-->Add Files to Project
这时,主工程的Resource Files中自动添加了lib
在主工程中需要用到其他库的位置加入库的头文件
(3). 通过工程的Link设置(推荐,lib可以统一管理)
提供了lib和其头文件
Project-->settings-->Link,选择Categery中的Input
在object/library modules里输入的动态链接库对应的.lib文件名
在Additional library path中输入动态链接库对应的.lib的路径
在主工程中需要用到其他库的位置加入库的头文件
(4). #pragma (lib, "filename.lilb")(不太推荐,lib没能统一管理)
提供了lib和其头文件
在主工程中需要用到其他库的位置加入#pragma (lib, "filename.lib")
在主工程中需要用到其他库的位置加入库的头文件
参考:(文章名称)
dll的def文件与__declspec(dllexport)导出函数方式比较
vs创建和调用dll和lib经验
阅读(5432) | 评论(0) | 转发(0) |