精华内容
下载资源
问答
  • DLL即动态链接库(Dynamic-Link Library)的缩写,相当于Linux下的共享对象。Windows系统中大量采用DLL机制,甚至内核的结构很大程度依赖于DLL机制。Windows下的DLL文件和EXE文件实际上是一个概念,都是PE格式的二...
    1. DLL即动态链接库(Dynamic-Link Library)的缩写,相当于Linux下的共享对象。Windows系统中大量采用DLL机制,甚至内核的结构很大程度依赖于DLL机制。Windows下的DLL文件和EXE文件实际上是一个概念,都是PE格式的二进制文件。一般的动态库程序有lib文件和dll文件,lib文件是编译时期连接到应用程序中的,而dll文件才是运行时才会被调用的。

    2. 为了根号的理解DLL,首先要有导入和导出的概念。
      a. 在ELF(Linux下动态库的格式),共享库中所有的全局函数和变量在默认情况下都可以被其它模块使用,即ELF默认导出所有的全局符号。DLL不同,需要显示地“告诉”编译器需要导出某个符号,否则编译器默认所有的符号都不导出。
      b. 程序使用DLL的过程其实是引用DLL中导出函数和符号的过程,即导入过程。对于从其他DLL导入的符号,需要使用“_declspec(dllimport)”显示声明某个符号作为导入符号在ELF中,使用外部符号时,不需要额外声明该符号从其他共享对象导入的

    3. 指定符号的导入导出一般有如下两种方法:
      (1)MSVC编译器提供了一系列C/C++的扩展***来指定符号的导入导出,即_declspec属性关键字***。
      a. _declspec(dllexport)表示该符号是从本DLL导出的符号
      b. _declspec(dllimport)表示该符号是从别的DLL中导入的
      (2)使用".def"文件来声明导入和导出符号,详细参考http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792099.html

    4. 创建DLL
      这里介绍的是使用VS2017创建DLL。
      (1)
      在这里插入图片描述
      (2)
      在这里插入图片描述
      (3)
      在这里插入图片描述
      (4)运行,生成.dll和.lib文件
      在这里插入图片描述

    5. DLL的调用方式
      windows下调用方式有两种,一种是“隐式调用”,另外一种是“显示调用”(这里主要介绍隐式调用)。
      a. 显示调用:不需要使用.lib文件,直接使用函数加载库,如下图所示:
      在这里插入图片描述
      b. 隐式调用
      (1)创建一个测试工程,将使用到的dll放到对应的运行目录下,同时将dll用到的导出类的头文件也拷贝到该工程下(include文件夹)、lib文件也放到该文件夹下(lib文件夹)。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      (2)配置工程属性
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      (3)在需要使用的地方,包含头文件即可使用
      在这里插入图片描述

    展开全文
  • dll动态链接库文件编写

    万次阅读 多人点赞 2017-12-02 20:50:52
    1.动态链接库dll)概述 没接触dll之前觉得它很神秘,就像是一个黑盒子,既不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其他dll调用来完成某项工作的函数,只有在其他模块...

    1.动态链接库(dll)概述

    没接触dll之前觉得它很神秘,就像是一个黑盒子,既不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其他dll调用来完成某项工作的函数,只有在其他模块调用dll中的函数时,dll才发挥作用。 
    在实际编程中,我们可以把完成某项功能的函数放在一个动态链接库里,然后提供给其他程序调用。像Windows API中所有的函数都包含在dll中,如Kernel32.dll, User32.dll, GDI32.dll等。那么dll究竟有什么好处呢?

    1.1 静态库和动态库

    • 静态库:函数和数据被编译进一个二进制文件(扩展名通常为.lib),在使用静态库的情况下,在编译链接可执行文件时,链接器从静态库中复制这些函数和数据,并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.exe)。当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。
    • 动态库:在使用动态库时,往往提供两个文件:一个引入库(.lib,非必须)和一个.dll文件。这里的引入库和静态库文件虽然扩展名都是.lib,但是有着本质上的区别,对于一个动态链接库来说,其引入库文件包含该动态库导出的函数和变量的符号名,而.dll文件包含该动态库实际的函数和数据。

    1.2 使用动态链接库的好处

    1. 可以使用多种编程语言编写:比如我们可以用VC++编写dll,然后在VB编写的程序中调用它。
    2. 增强产品功能:可以通过开发新的dll取代产品原有的dll,达到增强产品性能的目的。比如我们看到很多产品踢动了界面插件功能,允许用户动态地更换程序的界面,这就可以通过更换界面dll来实现。
    3. 提供二次开发的平台:用户可以单独利用dll调用其中实现的功能,来完成其他应用,实现二次开发。
    4. 节省内存:如果多个应用程序使用同一个dll,该dll的页面只需要存入内存一次,所有的应用程序都可以共享它的页面,从而节省内存。

    2. dll的创建

    dll的创建主要有两种方法:一是使用 __declspec(dllexport) 创建dll,二是使用模块定义(.def)文件创建dll。

    2.1 使用 __declspec(dllexport) 创建dll

    首先在VS中的Visual C++中创建一个Win32 Project,取名为Dll1。在Application Type中选择DLL,在Additional options中选择Empty project,即创建一个空的动态链接库工程。 
    这里写图片描述 
    然后为工程添加一个C++源文件:Dll1.cpp,假设我要实现的是加法和减法运算,则代码如下:

    __declspec(dllexport) int add(int a, int b){
        return a + b;
    }
    
    __declspec(dllexport) int subtract(int a, int b){
        return a - b;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    为了让dll导出函数,需要在每一个需要被导出的函数前面加上标识符:__declspec(dllexport)。 
    利用Build命令生成Dll1动态链接库,这时在Dll1/Debug目录下就会生成.dll文件和.lib文件,这两个文件即为所需的动态链接库的文件。 
    这里写图片描述 
    既然已经有了这个dll文件,是不是就可以在其他程序中访问该dll中的add和subtract函数了呢?必须注意的一点是:应用程序如果想要访问某个dll中的函数,那么这个函数必须是已经被导出的函数。 
    为了查看一个dll中有哪些导出函数,Visual Studio提供了一个命令行工具:Dumpbin。

    2.2 使用Dumpbin命令确认dll的导出函数

    首先在命令行中进入到VS的安装目录下,运行一个名为VCVARS32.bat的批处理程序(对于VS2013来说,该bat文件位于\VC\bin目录下),该文件的作用是用来创建VC++使用的环境信息。(注意,当在命令行界面执行VCVARS32.bat文件后,该文件设置的环境信息只在当前命令行窗口生效。) 
    然后输入dumpbin命令,即可列出该命令的使用方法: 
    这里写图片描述 
    那么想要查看一个dll提供的导出函数,在Dll1.dll文件所在目录下,在命令行中输入下述命令:

    dumpbin -exports Dll1.dll

    这里写图片描述

    在上图中可以看到我们导出了两个函数,但是导出函数的名称长得很奇怪,add导出函数的名称是“?add@@YAHHH@Z”,subtract导出函数的名称是“?subtrct@@YAHHH@Z”。这是因为在编译链接时,C++会按照自己的规则篡改函数的名称,这一过程称为“名字改编”。这会导致不同的编译器、不同的语言下调用dll发生问题。因此我们希望动态链接库文件在编译时,导出函数的名称不要发生变化。 
    为了实现这一目的,可以再定义导出函数时加上限定符:extern “C”,如

    extern "C" __declspec(dllexport) int add(int a, int b){
    //...
    }
    • 1
    • 2
    • 3

    但是这种方式只能解决C++和C语言之间相互调用时函数命名的问题。为了彻底解决这个问题,可以通过模块定义(.def)文件实现。

    2.3 使用模块定义(.def)文件创建dll

    使用def文件创建dll的话就不再需要__declspec(dllexport),因此将代码写成最原始的样子:

    int add(int a, int b){
        return a + b;
    }
    
    int subtract(int a, int b){
        return a - b;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    同时为工程创建一个后缀名为.def的文件,并添加进工程,编辑其内容为:

    LIBRARY Dll1
    
    EXPORTS
    add
    subtract
    • 1
    • 2
    • 3
    • 4
    • 5

    其中LIBRARY语句用于指定动态链接库的名称,该名称与生成的动态链接库名称一定要匹配。EXPORTS语句用于表明dll将要导出的函数,以及为这些导出函数指定的符号名。 
    将该模块定义文件链接到工程中,方法为工程属性页面>链接器>输入>模块定义文件中写入“Dll1.def”。 
    这里写图片描述 
    然后重新Build Solution,并用dumpbin工具查看现在dll导出的函数,可以发现函数的名字改编问题得到了解决! 
    这里写图片描述


    以上就是创建dll的两种方法,个人比较提倡使用模块定义(.def)文件创建dll,代码简洁的同时还没有名字改编的问题。 
    接下来我们来看看如何使用创建好的dll。

    3. dll的使用

    dll的使用也有两种方法,一是隐式链接的方式加载dll,二是显示加载方式加载dll。

    3.1 隐式链接方式加载dll

    为了更好地展示dll的使用,我首先创建了一个基于MFC的对话框程序,然后为其添加两个按钮。 
    这里写图片描述 
    将生成好的Dll1.dll和Dll1.lib复制到对话框程序所在的文件夹,然后在CXXXDlg.h中注册动态链接库的引入库文件。因为.lib文件包含了Dll1.dll中导出函数的符号名,相当于告诉对话框程序相关函数应该去dll中调用。

    #pragma comment(lib,"Dll1.lib")
    • 1

    然后在CXXXDlg.cpp中声明外部函数:

    _declspec(dllimport) int add(int a, int b);
    _declspec(dllimport) int subtract(int a, int b);
    • 1
    • 2

    这样我们就可以使用这两个函数了。为两个按钮添加事件响应程序,并添加如下代码:

    void CXXXDlg::OnBtnAdd()
    {
        // TODO: Add your control notification handler code here
        CString str;
        str.Format(_T("5 + 3 = %d"), add(5, 3));
        MessageBox(str);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行程序发现可以通过dll的导出函数来实现加法功能了。说明dll可以使用。 
    这里写图片描述

    3.2 显示加载方式加载dll

    另一种是通过LoadLiabrary函数显示加载dll。代码如下。需要注意的是这时候我们不再需要注册.lib文件,也不需要声明外部函数。只要在需要使用的地方调用dll文件即可。

    void CXXXDlg::OnBtnSubtract()
    {
        // TODO: Add your control notification handler code here
        HINSTANCE hInst;
        hInst = LoadLibrary(L"Dll1.dll");
        typedef int(*SUBPROC)(int a, int b);
        SUBPROC Sub = (SUBPROC)GetProcAddress(hInst, "subtract");
        CString str;
        str.Format(_T("5-3=%d"), Sub(5, 3));
        FreeLibrary(hInst);       //LoadLibrary后要记得FreeLibrary
        MessageBox(str);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里写图片描述

    3.3 两种加载方式对比

    通过以上的例子,可以看到隐式链接和动态加载两种加载dll的方式各有优点。

    • 隐式链接方式实现简单,一开始就把dll加载进来,在需要调用的时候直接调用即可。但是如果程序要访问十多个dll,如果都采用隐式链接方式加载他们的话,在该程序启动时,这些dll都需要被加载到内存中,并映射到调用进程的地址空间,这样将加大程序的启动时间。而且一般来说,在程序运行过程中只是在某个条件满足的情况下才需要访问某个dll中的函数,如在上述例子中,我只有在点击按钮时才需要访问dll,其他情况下并不需要访问。这样如果所有dll都被加载到内存中,资源浪费是比较严重的。
    • 显示加载的方法则可以解决上述问题,dll只有在需要用到的时候才会被加载到内存中。另外,其实采用隐式链接方式访问dll时,在程序启动时也是通过调用LoadLibrary函数加载该进程需要的动态链接库的。

    本文将创建一个简单的动态链接库,并编写一个控制应用程序使用该动态链接库,该动态链接库为“JAVA调用动态链接库DLL之JNative学习”中使用的DLL,只是项目及文件名称不同。

    创建动态链接库项目:
    1、打开Microsoft Visual Studio 2010,选择文件->新建->项目。


    2、在新建项目窗口中选择其他语言->Visual C++->Win32。


    3、选择Win32 项目,设置名称:simpleDLL,设置解决方案名:simpleDLL
    4、单击确定,在出现的Win32 应用程序向导的概述对话框中点击下一步。


    5、在应用程序设置中,选择应用程序类型下的DLL。


    6、勾选附加选项下的空项目。
    7、单击完成创建项目。
    向动态链接库添加类:
    1、添加新类头文件。右键单击simpleDLL项目,添加->新建项,选择头文件(.h),设置名称为simpleDLL,单击添加。



    2、添加新类源文件。右键单击simpleDLL项目,添加->新建项,选择C++ 文件(.cpp),设置名称为simpleDLL,单击添加。



    3、为新类添加内容。内容如下:

    头文件simpleDLL.h:

    [cpp] view plain copy
    1. //------------------ SimpleDLL.h ----------------  
    2.   
    3. #pragma once;  
    4.   
    5. //该宏完成在dll项目内部使用__declspec(dllexport)导出  
    6. //在dll项目外部使用时,用__declspec(dllimport)导入  
    7. //宏DLL_IMPLEMENT在SimpleDLL.cpp中定义  
    8. #ifdef DLL_IMPLEMENT  
    9. #define DLL_API __declspec(dllexport)  
    10. #else  
    11. #define DLL_API __declspec(dllimport)  
    12. #endif  
    13. DLL_API int add(int x, int y); //简单方法  
    14. DLL_API const wchar_t* getPlayUrl(const wchar_t* mgrIp, long mgrPort, long materialId);  
    15. DLL_API const char* getUrl(const char* mgrIp, long mgrPort, long materialId);  
    源文件simpleDLL.cpp:

    [cpp] view plain copy
    1. //------------------ SimpleDLL.cpp ----------------  
    2.   
    3. //注意此处的宏定义需要写在#include "SimpleDLL.h"之前  
    4. //以完成在dll项目内部使用__declspec(dllexport)导出  
    5. //在dll项目外部使用时,用__declspec(dllimport)导入  
    6. #define DLL_IMPLEMENT  
    7.   
    8. #include "SimpleDLL.h"  
    9. #include<Windows.h>  
    10. #include <intrin.h>  
    11. #include <stdlib.h>  
    12. #include <string.h>  
    13.   
    14. int DLL_API add(int x, int y)  
    15. {  
    16.     return x+y;  
    17. }  
    18.   
    19. DLL_API const wchar_t* getPlayUrl(const wchar_t* mgrIp, long mgrPort, long materialId)  
    20. {  
    21.     static wchar_t url[260] = { 0 };  
    22.     wcscpy_s(url, L"http://中文");  
    23.     wcscat_s(url, mgrIp);  
    24.     wcscat_s(url, L":");  
    25.     wchar_t szPort[20] = { 0 };  
    26.     _ltow_s(mgrPort, szPort, 10);  
    27.     wcscat_s(url, szPort);  
    28.     return url;  
    29. }  
    30.   
    31. DLL_API const char* getUrl(const char* mgrIp, long mgrPort, long materialId)  
    32. {  
    33.     static char url[260] = { 0 };  
    34.     strcpy_s(url, "http://中文");  
    35.     strcat_s(url, mgrIp);  
    36.     strcat_s(url, ":");  
    37.     char szPort[20] = { 0 };  
    38.     _ltoa_s(mgrPort, szPort, 10);  
    39.     strcat_s(url, szPort);  
    40.     return url;  
    41. }  

    创建引用动态链接库的应用程序:
    1、在解决方案上单击鼠标右键->添加->新建项目。


    2、在添加新项目中选择其它语言->Visual C++->Win32。


    3、选择Win32 控制台应用程序,设置名称:simpleDLLTest。
    4、单击确定,在出现的Win32 应用程序向导的概述对话框中点击下一步。


    5、在应用程序设置中,选择应用程序类型下的控制台应用程序。


    6、单击完成创建项目
    在控制台应用程序中使用类库的功能:
    1、为SimpleDLLTest.cpp添加内容。如下所示:

    [cpp] view plain copy
    1. // SimpleDLLTest.cpp : 定义控制台应用程序的入口点。  
    2.   
    3. #include "stdafx.h"  
    4. #include "../SimpleDLL/SimpleDLL.h" //添加头文件引用  
    5. #pragma comment(lib, "..\\..\\SimpleDLL\\Release\\SimpleDLL.lib") //添加lib文件引用   
    6. #include <process.h>  
    7. #include <locale.h>  
    8.   
    9. int _tmain(int argc, _TCHAR* argv[])  
    10. {  
    11.     setlocale(LC_ALL, "chs"); //配置地域化信息为简体中文,否则打印出来的中文是乱码  
    12.     wprintf(L"getPlayUrl: %s\r\n", getPlayUrl(L"127.0.0.1", 10087, 1));  
    13.   
    14.     printf("getUrl: %s\r\n", getUrl("127.0.0.1", 10087, 1));  
    15.     system("pause");  
    16.     return 0;  
    17. }  
    2、引用simpleDLL项目。右键单击SimpleDLLTest项目,选择项目依赖项。


    3、依赖于窗口中勾选SimpleDLL,单击确定。


    4、设置SimpleDLLTest项目为活动项目。右键单击SimpleDLLTest项目,选择设为启动项目。


    6、生成解决方案。Debug运行结果如下:


    注意:现在创建的DLL只能由c++调用,C语言等其它语言是调用不了的!

    我们来用工具看一下,在解决方案上单击鼠标右键,在Windows资源管理器中打开文件夹


    我编译的是Release版本,所以打开Release文件夹,找到SimpleDLL.dll文件,用Depends工具打开它


    目前编译的版本对MSVCR100.DLL还有依赖,这样复制到其它没有安装VS2010的电脑上是用不了的;

    在项目上单击鼠标右键,属性:


    在左侧的配置属性中选择常规,在右侧找到MFC的使用,选择在静态库中使用MFC


    这里是修改MFC的使用,还有另一种方法:vs2010发布时去除msvcp100.dll和msvcr100.dll图解说明

    再看函数,带有一些特殊字符,这样c++之外其它语言是调用不了的;我们需要在头文件的函数声明中添加extern "C"标志,代码如下:

    [cpp] view plain copy
    1. //------------------ SimpleDLL.h ----------------  
    2.   
    3. #pragma once;  
    4.   
    5. //该宏完成在dll项目内部使用__declspec(dllexport)导出  
    6. //在dll项目外部使用时,用__declspec(dllimport)导入  
    7. //宏DLL_IMPLEMENT在SimpleDLL.cpp中定义  
    8. #ifdef DLL_IMPLEMENT  
    9. #define DLL_API __declspec(dllexport)  
    10. #else  
    11. #define DLL_API __declspec(dllimport)  
    12. #endif  
    13. extern "C" DLL_API int add(int x, int y); //简单方法  
    14. extern "C" DLL_API const wchar_t* getPlayUrl(const wchar_t* mgrIp, long mgrPort, long materialId);  
    15. extern "C" DLL_API const char* getUrl(const char* mgrIp, long mgrPort, long materialId);  
    重新编译,再Depends工具打开它,可以发现依赖项已经没有了,函数名称也正常了:


    参考:演练:创建和使用动态链接库 (C++)

    解决方案源码下载:http://download.csdn.net/detail/testcs_dn/7411383


    展开全文
  • 动态链接库dll文件解析

    万次阅读 2017-07-25 21:07:01
    生成动态链接库dll文件)1、使用VS生成动态链接库的步骤: (1)新建一个win32控制台工程,并在应用程序设置窗口中选择“Dll”选项,附加选项选择“空项目”。如下图:(2)创建完工程之后,添加源文件,在源文件...

    生成动态链接库(dll文件)

    1、使用VS生成动态链接库的步骤:
    (1)新建一个win32控制台工程,并在应用程序设置窗口中选择“Dll”选项,附加选项选择“空项目”。如下图:

    这里写图片描述

    (2)创建完工程之后,添加源文件,在源文件中写上想导出到dll文件的函数。函数声明之前应该加上“_declpec(dllexport)”表示函数输出为动态链接库。除此之外,还要在函数名前面加上调用约定。因为c/c++语言默认的调用约定是“_cdecl”,如果采用“_cdecl”调用约定,可以不用写。如果使用“_stdcall”和“_fastcall”调用约定,则要进行说明。下图是一个简单的例子:

    这里写图片描述

    图中有三个函数,分别采用的调用约定是“_cdecl”,”_stdcall”和”_fastcall”。调用约定会给函数名加上一些修饰,不同的调用约定给函数名的修饰是不一样的,因此要慎重地使用调用约定。
    (3)编译。在菜单栏上的“生成”中点击“生成解决方案”即可生成动态链接库。如果编译成功,到工程文件夹下面的Debug文件夹里头可以找到后缀名为dll和lib连个文件。其中,lib文件保存着函数的相关定义和索引,其作用类似于头文件,而dll文件是函数的实现部分,是不可缺少的。

    2、生成动态链接库时应注意的事项
    (1)函数声明前面加上“_declspec(dllexport)”表明函数将输出为动态链接库,是必不可少的,
    (2)导出的函数如果不是采用C/C++默认的“_cdecl”的调用约定,则要特别说明。使用调用约定时,应考虑到以后调用该函数的问题,调用时使用的调用约定只有与生成时设置的调用约定相一致时,才能调用。也就是说,如果生成dll文件时,给函数设置的调用约定为“_stdcall”,而调用该函数时使用的调用约定是“_cdecl”,那么将会无法找到该函数。
    (3)在相同的调用约定下,采用不同的编译器,对函数名的修饰是不一样的。比如,同是采用”_cdecl”调用约定,C语言和C++语言导出的dll文件中,函数的修饰名是不一样的。如果要C语言风格的dll文件,就要再加上“extern C”进行修饰,或者把源文件名的后缀改为.c。如果是要C++风格的dll文件,则源文件名后缀必须为.cpp。下图是生成C风格的dll文件例子:

    这里写图片描述

    前两个函数将会导出为C风格的dll,而后一个函数被导出为C++风格的dll。如果把源文件后缀改为.c,那么所有的函数都会被导出为C风格的dll。

    调用动态链接库

    1、C语言调用C语言的dll文件
    如图,有三个函数被导出到dll,前两个是C语言风格的,后一个是C++风格的。C语言是无法用常规方法调用C++风格的dll。

    这里写图片描述

    (1)新建一个控制台工程,添加一个源文件,并将源文件的后缀改为.c,告诉编译器这是一个C语言程序。
    (2)将lib文件和dll文件放在与源文件相同的目录下。
    (3)在程序的开头要加上#pragma comment(lib,”mydll.lib”),第一个参数必须是lib,第二个个参数是lib文件的文件名。函数调用前要先声明,函数的声明需要加上调用约定修饰。如下图:

    这里写图片描述

    (4)生成解决方案,如果没有错误,运行程序将会输出正确的结果。

    2、C++调用C语言的dll
    在C++程序中,要调用C语言的dll,要声明一下调用的函数是C语言风格的。方法是在函数声明时加上 extern “C”修饰。新建一个控制台工程,添加一个cpp文件,源文件中的代码如图所示:

    这里写图片描述

    3、C++调用C++的dll

    C++调用C++的dll,只需在函数声明时加上调用约定修饰。如下图:

    这里写图片描述

    4、动态加载dll
    以上的调用dll的方法都是属于静态调用类型的,一般是需要有lib文件的。如果采用动态加载dll,则不需要lib文件,只需dll文件就足够了。动态加载dll需要用到两个函数,一个是LoadLibrary,另一个是GetProcAddress,这两个函数都包含在window.h头文件中。值得注意的是,动态加载dll文件的方法,一般只能调用C语言风格的,且调用约定为“_cdecl”的函数。下图是动态加载dll的例子:

    这里写图片描述

    上面说,动态加载dll的方法一般适合调用C风格的、且调用约定为“_cdecl”的函数,那是因为C风格的、且调用约定为“_cdecl”的函数的函数名不会被修饰,源文件写的是什么样子,dll文件中就是什么样子。当然,调用C++风格的,且不是“_cdecl”约定的函数也是可以的,只是很麻烦。由于编译器类型(C或C++)和调用约定都会对函数的名称进行修饰,使得dll文件中的函数名称不再是源文件所写的那样。GetProcAddress函数是通过函数名来查找函数入口的,因此,只要知道dll文件中的函数修饰名,将函数修饰名传给GetProcAddress函数,就可以获得函数的指针。那么如何知道dll文件中函数的修饰名呢?这就需要用到一些分析软件了,比如depends这个软件就可以查看dll文件的函数名称。下图是使用depends软件查看dll中的函数。可以看到Add和Multi函数在dll文件中的修饰名分别是?Add@@YGHHH@Z和?Multi@@YGHHH@Z。

    这里写图片描述

    是不是所有的函数都可以通过查找其在dll文件中的修饰名来获取函数指针呢?为此,我做了一些实验,实验未必充分,但也可以得出一些结论:
    (1)往GetProcAddress函数中传入函数在dll的修饰名,如果dll中的函数采用的是“_cdecl”调用约定,无论是C风格的还是C++风格的,都不会报错,函数调用的结果也是正确的。下图是调用采用“_cdecl”调用约定的函数:

    这里写图片描述

    这里写图片描述

    从实验结果来看,对于调用约定为“_cdecl”的函数,只要能通过depends找到函数的修饰名,就可以调用该函数。函数调用的结果是正确的。

    (2)往GetProcAddress函数中传入函数在dll的修饰名,如果dll中的函数采用的是“_stdcall”调用约定,程序运行时会报错,但是忽略错误,调用的结果却是正确的。下图是调用“_stdcall”约定的函数:

    这里写图片描述
    这里写图片描述

    从实验结果来看,调用“_stdcall”约定的函数,是会报错的,但结果仍然正确。

    (3)往GetProcAddress函数中传入函数在dll的修饰名,如果dll中的函数采用的是“_fastcall”调用约定,那么程序运行不会报错,但调用结果却是错误的!下图是调用“_fastcall”约定的函数:

    这里写图片描述
    这里写图片描述

    很让人郁闷的是,调用“_fastcall”约定的函数,程序运行时不会报错,但是调用的结果却是错得离谱。2+3=-1672607445这是什么鬼?原因不明。

    (4)结论:通过使用LoadLibrary函数和GetProcAddress函数来动态加载dll文件,这种方法只适用于调用“_cedcl”约定的函数,只要是采用“_cdecl”约定的,不管是C风格的还是C++风格的,都可以正常地被调用。如果是其他调用约定,无论是C风格还是C++风格的函数,都无法正常调用。

    展开全文
  • C#中创建DLL动态链接库)及其使用

    万次阅读 多人点赞 2019-08-11 17:40:57
    动态链接库(也称为 DLL ,即为“ Dynamic Link Library ”的缩写)是 Microsoft Windows 最重要的组成要素之一,打开 Windows 系统文件夹,你会发现文件夹中有很多 DLL 文件, Windows 就是将一些主要的系统功能以 ...

    一、DLL 与应用程序

    动态链接库(也称为 DLL ,即为“ Dynamic Link Library ”的缩写)是 Microsoft Windows 最重要的组成要素之一,打开 Windows 系统文件夹,你会发现文件夹中有很多 DLL 文件, Windows 就是将一些主要的系统功能以 DLL 模块的形式实现。

    动态链接库是不能直接执行的,也不能接收消息,它只是一个独立的文件,其中包含能被程序或其它 DLL 调用来完成一定操作的函数 ( 方法。注: C# 中一般称为“方法” ) ,但这些函数不是执行程序本身的一部分,而是根据进程的需要按需载入,此时才能发挥作用。

    DLL 只有在应用程序需要时才被系统加载到进程的虚拟空间中,成为调用进程的一部分,此时该 DLL 也只能被该进程的线程访问,它的句柄可以被调用进程所使用,而调用进程的句柄也可以被该 DLL 所使用。在内存中,一个 DLL 只有一个实例,且它的编制与具体的编程语言和编译器都没有关系,所以可以通过 DLL 来实现混合语言编程。 DLL 函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。

    下面列出了当程序使用 DLL 时提供的一些优点: [1]

    1)  使用较少的资源

    当多个程序使用同一个函数库时, DLL 可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序,而且可以大大影响其他在 Windows 操作系统上运行的程序。

    2)  推广模块式体系结构

    DLL 有助于促进模块式程序的开发。这可以帮助您开发要求提供多个语言版本的大型程序或要求具有模块式体系结构的程序。模块式程序的一个示例是具有多个可以在运行时动态加载的模块的计帐程序。

    3)  简化部署和安装

    当 DLL 中的函数需要更新或修复时,部署和安装 DLL 不要求重新建立程序与该 DLL 的链接。此外,如果多个程序使用同一个 DLL ,那么多个程序都将从该更新或修复中获益。当您使用定期更新或修复的第三方 DLL 时,此问题可能会更频繁地出现。

    二、 DLL 的创建及调用

    1、创建:新建 -> 项目->类库  ,名称为:dlltest

       

    2、添加代码

    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace dlltest
    
    {
        public class Class1
        {
            //你自己要编译成动态库的程序,以下为示例
    
            public void ShowMessage(string text)
            {
                Console.WriteLine("你调用了动态链接库!");
                MessageBox.Show(text,"消息提示");
            }
    
        }
    }

    然后生成解决方案,在工程bin/Debug下即可找到名称为dlltest.dll的文件

    3、使用:

    1)添加引用 
                右击项目-添加引用-浏览 找到本地的dll文件

    image

    2)using 该dll文件里面代码的名称空间

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    //using 要引用的dll文件的命名空间
    using dlltest;
     
    namespace DllExample
    {
        class Program
        {
            static void Main(string[] args)
            {
                dlltest.MyClass myTest = new dlltest.MyClass();
                myTest.ShowMessage();
            }
        }
    
    展开全文
  • DLL文件动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows提供的DLL文件中包含了允许基于Windows的程序在Windows环境下操作的许多函数和资源。  DLL多数情况下是...
  • 版权声明:转载需标明该文链接。... 本文用的是vs2017,vs主要功能基本一致,此方法多个版本都适用。 生成链接库的方式有两种:一种...以下详细讲解动态链接库.dll的生成&调用,文末简单讲解静态链接库.lib的生成...
  • (1).h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。 附加依赖项的是.lib 不是.dll 若生成了DLL ,则肯定也生成 LIB文件 如果要完成源代码的编译和链接,有...H文件 作用是:声明函数接口 DLL文件 作用
  • 一、创建动态链接库(生成.dll .lib 两个文件文件→新建→项目 选择控制台应用程序 选择DLL,勾选空项目,点击完成 添加源文件A.cpp(只要写被调用的函数) #include&lt;iostream&gt; using ...
  • 2 动态链接库编程之基础概念 DLL(Dynamic Linkable Library)的概念 ...静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。但是若
  • 动态链接库最大的优势在于可以提供给其他应用程序共享的资源,最小化应用程序代码的复杂度,其中一个十分重要的功能就是dll可以导出封装函数的功能。导出函数有两种主要方式,分别是静态导入和动态导入,本文主要...
  • DLL动态链接库】labview调用DLL动态链接库入门实例

    千次阅读 多人点赞 2019-03-27 16:46:56
    目的:生成一个DLL,用labview调用,实现加法乘除的功能。 1、新建一个工程。 2、添加头文件,头文件里面申明函数和变量。 三个输入,分别是2个参数和一个代表运算法,返回值为double类型。 __declspec(dll...
  • 在Java程序中加载dll动态链接库有两种方法: 第一种:通过调用System.loadLibrary(String filename); 第二种:通过调用System.load(String filename)方法。 第一种参数filename直接写动态链接库的名字,例如System....
  • 1、dll动态库文件项目生成属性中要勾选“XML文档文件”注意:1)、要选中项目,查看项目属性,选中解决方案是找不到的。2)、XML文件的名字不要修改。2、添加引用时XML文件要与DLL文件在同一个目录下。3、如果要是...
  • 注:.dll文件是Windows平台下的动态链接库文件,在Linux平台,有响应功能的文件是.so文件,.so文件接口的封装也可以参考此文的思路 目录 一、DLL项目结构介绍 二、DLL项目示例 1.文件 My_Dll_Project.h 2.文件...
  • C#编写动态链接库类库dll文件

    万次阅读 2017-04-16 18:22:34
    1、DLL 即:动态链接库  DLL是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数...
  • Matlab的计算功能是很强大的,但是软件经常要用到Matlab解算法,造成集成不便,一个好的解决方法是将Matlab中计算程序封装成函数,再编译成动态链接库供软件使用,方法如下: 首先将Matlab中的算法封装成函数,我在...
  • 在工作过程中,需要用Teigha将CAD的一些基本操作嵌入到一个程序中,但是我们只有C#的TD_Mgd_3.03_9.dll,而之前的工程是用C++做的,所以涉及到怎么用C++语言调用C#生成的dll。这里就不讲CAD的二次开发是个什么东西,...
  • 但是动态链接库,对头文件和库都要进行相应的处理。 创建一个项目,有几种方案,其中,在应用程序类型中选择dll,在附加项中选择导出符号,选择导出符号这样做比较方便,很多东西都帮你做好了。 生成一个dll.h dll....
  • 动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。 以上是百度百科对DLL的释义,对DLL的科普到此结束,下面开始...
  • LabVIEW调用DLL动态链接库

    千次阅读 2020-02-04 21:27:01
    LabVIEW调用DLL动态链接库 示例一 通过调用DLL实现数组求和。输入一个10个元素的数组,返回全部元素之和。 1.生成DLL VS中选择创建动态链接库项目 在头文件和源文件文件夹分别创建相应的.h .cpp文件 在test.h中...
  • C++中编译生成dll(动态链接库)文件

    千次阅读 2013-12-02 09:01:26
    主要是在函数里面的入口函数前添加extern "C" __declspec(dllexport) 例如: extern "C" __declspec(dllexport) void StartLangRec()
  • 一.准备工作 注:操作系统为64bit 本文使用tensorflow dll 编译tensorflow,输出dll和lib。...工程所需软件及测试源码下载链接 bazel: https://download.csdn.net/download/sinat_19758811/112...
  • 链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,形成最终生成可执行代码的过程。 二、编译过程 编译过程分为:预编译过程,编译过程,汇编过程。 2.1、预编译过程 读取.c或.cpp源程序,对其中...
  • VB编写.DLL动态链接库文件

    千次阅读 2010-10-01 19:05:00
    VB编写.DLL动态链接库文件 VB一般可以生成两种特殊的DLL,一个是ActiveX DLL和ActiveX Control(*.ocx)。这两种DLL都是VB支持 的标准类型,在VB自身的例子中有,你可以参考。更详细的介绍可以参考...
  • 动态链接库DLL

    千次阅读 2016-05-08 23:20:17
    它是Dynamic Link Library 的缩写形式,DLL 是一个包含可由多个程序同时使用的代码和数据的DLL不是可执行文件动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 ...
  • VS2013创建dll动态链接库文件心得

    万次阅读 热门讨论 2014-04-17 17:20:40
    关于创建动态链接库文件,并在程序运行过程中连接调用,我是这么理解的; 首先要生成一个DLL文件和lib文件,才能够供给其他程序动态调用或者静态调用。这篇日志是关于动态调用的; 接下来是总结的一些具体步骤: ...
  • 易语言模块及DLL动态链接库编写

    千次阅读 2020-07-07 09:08:11
    在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个...
  • lib是静态库,dll一般是动态链接库(也有可能是别的) 比如要编译个exe,lib在编译的时候就会被编译到exe里,作为程序的一部分 而dll是不被编译进去,是运行的时候才调入的(可能是exe刚运行就调入,也可能运行了...
  • VS2017创建DLL动态链接库方法

    千次阅读 2019-02-20 12:11:58
    2.选择C++下面的windows桌面,右边选择动态链接库DLL)。新建成功之后,默认为x86平台。 按照你自己的需求更换平台,必须调用的和被调用的dll同为一个平台。 3.新建之后,在头文件中添加mydll.h,内容为: #...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 86,841
精华内容 34,736
关键字:

dll文件动态链接库