样例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 导出, http://msdn.microsoft.com/zh-cn/library/d91k01sh(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") 在主工程中需要用到其他库的位置加入库的头文件