VS2015 创建及使用DLL,以及静态lib

创建DLL方法一

  1. 使用IDE创建Dll工程
    1.1 在既有解决方案中创建Dll工程使用 File->添加 dll项目
    1.2 需要新建解决方案时 使用File->新建 dll项目
    VS2015 创建及使用DLL,以及静态lib_第1张图片
    是否需要导出符号,是否需要预编译头 可以自行决定
    使用导出符合可以 导出一个完整的Dll实例 如下
    VS2015 创建及使用DLL,以及静态lib_第2张图片
    其中DllProject.h DllProject.cpp 是示例的头文件及其实现
    Dllmain.cpp 是dll的main函数入口

    【DllMain函数】
    Windows在加载DLL时,需要一个入口函数,就像控制台程序需要main函数一样。有的时候,DLL并没有提供DllMain函数,应用程序也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的默认DllMain函数版本,并不意味着DLL可以抛弃DllMain函数。
    根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数,这就说明不能在客户端直接调用DllMain函数,DllMain函数是自动被调用的。
    DllMain函数在DLL被加载和卸载时被调用,在单个线程启动和终止时,DllMain函数也被调用。参数ul_reason_for_call指明了调用DllMain的原因,有以下四种情况:
    DLL_PROCESS_ATTACH:当一个DLL被首次载入进程地址空间时,系统会调用该DLL的DllMain函数,传递的ul_reason_for_call参数值为DLL_PROCESS_ATTACH。这种情况只有首次映射DLL时才发生;
    DLL_THREAD_ATTACH:该通知告诉所有的DLL执行线程的初始化。当进程创建一个新的线程时,系统会查看进程地址空间中所有的DLL文件映射,之后用DLL_THREAD_ATTACH来调用DLL中的DllMain函数。要注意的是,系统不会为进程的主线程使用值DLL_THREAD_ATTACH来调用DLL中的DllMain函数;
    DLL_PROCESS_DETACH:当DLL从进程的地址空间解除映射时,参数ul_reason_for_call参数值为DLL_PROCESS_DETACH。当DLL处理DLL_PROCESS_DETACH时,DLL应该处理与进程相关的清理操作。如果进程的终结是因为系统中有某个线程调用了TerminateProcess来终结的,那么系统就不会用DLL_PROCESS_DETACH来调用DLL中的DllMain函数来执行进程的清理工作。这样就会造成数据丢失;
    DLL_THREAD_DETACH:该通知告诉所有的DLL执行线程的清理工作。注意的是如果线程的终结是使用TerminateThread来完成的,那么系统将不会使用值DLL_THREAD_DETACH来执行线程的清理工作,这也就是说可能会造成数据丢失,所以不要使用TerminateThread来终结线程。以上所有讲解在工程DLLMainDemo(工程下载)都有体现。


stdafx.h stdafx.cpp是预编译头文件及实现文件 targetver.h可以设置所支持的windows 平台版本 `DllProject.h文件解析如下`
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLLPROJECT_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DLLPROJECT_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DLLPROJECT_EXPORTS   //定义在 工程->属性->c/c++ 预处理器定义 为工程宏定义
#define DLLPROJECT_API __declspec(dllexport) //在dll项目中 为dllexport
#else
#define DLLPROJECT_API __declspec(dllimport)  //在使用该dll的项目中为 dllimport
#endif

// 此类是从 DllProject.dll 导出的
class DLLPROJECT_API CDllProject {
public:
    CDllProject(void);
    // TODO:  在此添加您的方法。
    static double Add(double a, double b);//添加的方法
};

extern DLLPROJECT_API int nDllProject; //非类变量示例

extern "C" DLLPROJECT_API int fnDllProject(void);//非类函数示例
`DllProject.cpp解析如下`
// DllProject.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "DllProject.h"


// 这是导出变量的一个示例
DLLPROJECT_API int nDllProject=0;   //变量定义用DLLPROJECT_API限定

// 这是导出函数的一个示例。
DLLPROJECT_API int fnDllProject(void)
{
    return 42;
}

// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 DllProject.h
CDllProject::CDllProject()
{
    return;
}

//自定义方法
double CDllProject::Add(double a, double b) //类已限定了DLLPROJECT_API 此方法不用重复限定
{
    return a + b;
}
**不使用 导出符号属性** ![这里写图片描述](https://img-blog.csdn.net/20180603092239191?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpZ3Vhbmd4aWxneA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 自行添加头文件 实现文件 导出限定宏定义 等 **编译以上的dll工程可以得到dll库以及lib符号库(包含函数声明,变量声明等但不包含实现)**

创建DLL方法二 不常用

函数导出方式
在DLL的创建过程中,我使用的是_declspec( dllexport )方式导出函数的,其实还有另一种导出函数的方式,那就是使用导出文件(.def)。你可以在DLL工程中,添加一个Module-Definition File(.def)文件。.def文件为链接器提供了有关被链接器程序的导出、属性及其它方面的信息。
对于上面的例子,.def可以是这样的:

LIBRARY “DLLDemo2”
EXPORTS
Add @ 1 ;Export the Add function 因为指定了函数序号 所以extern “C”可以省略
Module-Definition File(.def)文件的格式如下:

LIBRARY语句说明.def文件对应的DLL;
EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号有一定的作用)。
使用def文件,生成了DLL
VS2015 创建及使用DLL,以及静态lib_第3张图片
整体如下
VS2015 创建及使用DLL,以及静态lib_第4张图片
以上dll工程 创建完毕,编译之后 dll lib库生成位置默认为 解决方案下的debug目录中


使用DLL库

在同一个解决方案下使用

  1. 添加引用 如下图
    VS2015 创建及使用DLL,以及静态lib_第5张图片
    VS2015 创建及使用DLL,以及静态lib_第6张图片
  2. 添加头文件 附加包含目录
    dll库头文件所在目录 此时引用头文件时,可以找到相应头文件
    VS2015 创建及使用DLL,以及静态lib_第7张图片
    添加 附加包含目录
    VS2015 创建及使用DLL,以及静态lib_第8张图片

  3. 使用库函数
    VS2015 创建及使用DLL,以及静态lib_第9张图片

在不同的解决方案下使用dll库

静态使用dll库 需要头文件,导出库lib文件(生成dll时生成的文件与静态库lib同名但内容不同)以及dll文件

  1. 设置库头文件目录 附加包含目录 工程属性->C/C++->常规 附加包含目录 包含头文件时使用
  2. 设置l附加库目录 lib文件所在目录 工程属性->链接器->常规 附加库目录
  3. 设置依赖库 工程属性->链接器->输入->附加依赖项 具体到lib的全路径
    相当于在相应文件加入 #pragma comment(lib, “xxx\libconfig.lib”)
    #pragma comment(lib, “libconfig.lib”)//此时libconfig.lib需要和.h文件在同级目录下
    如下图 主要添加编译器 编译后的函数及变量 类等声明
    VS2015 创建及使用DLL,以及静态lib_第10张图片
  4. dll动态库的设置 使得可以找到dll库 定义 方法如下
    方法1. 放置到解决方案下的 debug/release 目录下,与平台无关,可直接复制工程到别的电脑
    方法2. 放置到win32 system32 或者system目录下相当于放置在已有环境变量目录下 平台有关
    方法3. 设置dll动态库路径到 环境变量Path中 与平台有关 需要重启以使得环境变量生效
    方法4. 设置工作目录为 dll库所在目录 工作目录为程序启动后唯一的默认目录 文件读写就会自动寻找该目录,例如这种情况下,程序就会从工作目录中读取dll库,默认情况下工作目录为$(ProjectDir),所以 同方法1的原理相同,也因为如此,该目录作为默认目录会被放入别的文件
    选择当前工程,右击”属性” -> “配置属性” -> “调试”,在”工作目录”设置dll的路径
    优点:跨平台(拷贝到其他平台不用改动)
    缺点:目录不能很干净,因为生成的文件会自动放到这个目录下
    VS2015 创建及使用DLL,以及静态lib_第11张图片
    方法5. 创建一个文件夹lib,里面放入所有需要的dll文件,右击”属性” -> “生成事件” -> “预先生成事件”,输入命令”copy .\lib*.dll ..\Debug\”,在预处理的时候把dll文件拷贝到Debug目录下。
    VS2015 创建及使用DLL,以及静态lib_第12张图片
    以上均可以使得项目找到dll库的定义

动态使用dll库 只需要Dll 不需要lib文件以及头文件

按照上述方法,放置好dll文件,之后LoadLibrary载入dll
getProcAddress获取dll 接口 使用函数指针指向该接口,使用函数指针指向该指针
释放dll FreeLibray(HMODULE)
方法1:显示连接


#include "stdafx.h"
#include
#include

int main()
{
    HMODULE hMoudle = LoadLibrary(_T("DllProject.dll"));  //载入dll
    if (hMoudle == NULL || INVALID_HANDLE_VALUE == hMoudle)
    {
        FreeLibrary(hMoudle); //释放dll
        return -1;
    }
    double a = 5, b = 10;
    typedef double(*TYPE_ADD)(double, double);//函数指针
    typedef int(*TYPE_FUN)(void);
    //特别注意 C与C++风格的函数签名 是不同的,C++风格的签名与参数有关
    TYPE_FUN Add = (TYPE_FUN)GetProcAddress(hMoudle, "fnDllProject");
    if (NULL == Add)
    {
        return -1;
        FreeLibrary(hMoudle);
    }
    std::cout << Add()<< std::endl;
    system("pause");
    FreeLibrary(hMoudle);
    return 0;
}

方法2:def文件定义输出时,可以使用EXPORTS 输出序号来获取函数

#include 
#include 
using namespace std;
typedef int (*AddFunc)(int a, int b);
int main(int argc, char *argv[])
{
      HMODULE hDll = LoadLibrary("DLLDemo2.dll");
      if (hDll != NULL)
      {
            AddFunc add = (AddFunc)GetProcAddress(hDll, MAKEINTRESOURCE(1)); //使用EXPORTS定义函数序号1
            if (add != NULL)
            {
                  cout<2, 3)<

查看Dll接口

vs自带dumpbin 查看
VS2015 创建及使用DLL,以及静态lib_第13张图片

Dependency Walker工具查看该DLL
https://www.cnblogs.com/ring1992/p/6003248.html

生成与使用静态库lib

https://blog.csdn.net/wzhwhust/article/details/53321532

你可能感兴趣的:(IDE配置快捷键)