精华内容
下载资源
问答
  • 动态链接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++风格的函数,都无法正常调用。

    展开全文
  • VS2013 中生成lib和dll库文件

    万次阅读 2014-03-15 14:53:47
    ①新建项目-->win32-->win32项目-->输入项目名为DllTest-->选择Dll-->选择空项目-->完成 ②添加头文件和源文件并命名为DllTest.h和DllTest.cpp(方法:分别在头文件和源文件 :右键---添加---新建项) ③头文件...

    ①新建项目-->win32-->win32项目-->输入项目名为DllTest-->选择Dll-->选择空项目-->完成


    ②添加头文件和源文件并命名为DllTest.h和DllTest.cpp(方法:分别在头文件和源文件  :右键---添加---新建项)


    ③头文件和源文件的定义(这里我们只实现加法运算)

    // DllTest.h

    #ifdef DLL_API
    #else
    #define DLL_API __declspec(dllexport)
    #endif
    // 声明要导出的函数
    DLL_API int add(int a, int b);


    // DllTest.vpp

    #define DLL_API __declspec(dllexport)
    
    #include "DllTest.h"
    
    int add(int a, int b)
    {
    	return a + b;
    }

    ④我们编译运行一下,因为不是完整的文件,这里会报错,不过没关系,这是我们找到文件存放的位置,会发现DeBug文件中会包含

    这些生成的文件,这里我们只关心.dll和.lib文件。在Debug同级目录下,在DllTest文件中,会找到DllTest.h文件

    .dll文件即使动态链接库,.lib文件是程序开发用的导入库,.h文件包含导出函数的声明


    ⑤我们再新建一个项目,命名为TestForDll,选择win32 控制台应用程序



    ⑥将我们④中的三个文件存放到TestForDll目录下的TestForDll文件中


    如果我们直接存放在TestForDll文件中会出现    error C1083: 无法打开包括文件: “DllTest.h”

    如果我们这时只把DllTest.h放进去的话会出现错误:error LNK1104: 无法打开文件“DllTest.lib”

    这时再把.lib文件放入TestForDll目录下的TestForDll文件中,就可以正常的编译运行


    使用#pragma comment(lib,"DllTest")命令链接到DllTest.lib库。当然我们也可以使用项目---属性---配置属性----链接器---输入-----附加依赖项中添加DllTest.lib



    这里给出main函数的实现

    #include <stdio.h>
    #include "DllTest.h"
    
    #pragma comment(lib,"DllTest.lib")
    
    int main()
    {
    	int a = 3;
    	int b = 2;
    	printf("a+b=%d\n", add(a,b));
    	return 0;
    }

    备注:如果我们把没把.dll文件放在debug目录下,当关闭程序,重新启动的时候,会出现找不到.dll文件的错误

    因此我们最好要把.dll文件放在debug目录下

    展开全文
  • 怎样编写自己的DLL库文件

    千次阅读 2012-07-30 19:58:03
    转载请声明出处!!!谢谢!!! 经常我们需要利用我们以前编写某些程序里面的某些函数,但是我们总不能每次都把原来文件打开...所以我们就要自已写一个,以后需要的时候然后调用就行了。现在我们就来讨论怎样编写自

    转载请声明出处!!!谢谢!!!

    经常我们需要利用我们以前编写某些程序里面的某些函数,但是我们总不能每次都把原来文件打开然后复制粘贴吧,太麻烦了,有人想到了一些暴力的方法,如果那个文件只是一个实现函数的功能的文件,没有主函数的话,就#include<XXX.c/.cpp>,然后编译相当暴力。明显这样会急剧增大我们最终生成的.exe文件大小。所以我们就要自已写一个库,以后需要的时候然后调用就行了。现在我们就来讨论怎样编写自己的库。

    在开始之前先弄明白几个概念:动态链接库、动态链接库、动态链接、静态链接。

    静态链接库

    通俗说就是不管现在需不需要在生成可执行文件的时候全部编译进去。不管暂时能不能用到,先拿来再说,明显这样生成的可执行文件会很大。这是静态链接库致命的缺点,因为很多软件虽然对大小没有要求但是过分的冗余是让人无法接受的。但是这也是产生静态链接库优点的原因,避免了dll hell的问题。

    动态链接库

    与静态链接库相反,动态连接库就是在需要的时候才调用。因此动态链接库显得简洁方便,但是产生了 dll hell的问题。什么是dll hell呢?简单的比喻一下。我喜欢吃包子,静态链接库相当于与,为了吃包子我在自己家里开了家包子店,虽然目前不吃,但是想吃的时候就会有,不会产生别人跟我抢包子的现象。动态链接库相当于我家门口开了家包子店,这个包子店不是我家的,每次想吃包子才去包子店,因此节省了我家的地方,但是会产生别人跟我竞争包子的显现,同时今天卖的包子不一定符合我的口味(相当于dll版本不对),更主要的是包子是别人做的啊,安全问题咋办?谁对我有仇包子里面下毒怎么办?因此动态链接库是有一定的风险的。

    静态链接

    静态链接和动态链接是动态链接库实现的两种方法。静态链接就是直接在程序运行前将需要的运行库包含进来,就跟#define 一样,是原地展开。在程序运行前检查这些库,如果某个库不存在,程序无法运行。

    动态链接

    动态链接是在程序运行的时候需要了才去加载。例如我有个读取数据库的函数做成了dll,只有当我点击了查找按钮之后,才会加载这个库然后实现某些功能,如果这个库不存在,紧紧是某些功能无法实现,对程序其他功能没有影响。

       了解了几个概念之后,开始介绍怎样编写和应用DLL文件

    1、编写dll文件。

    打开VC 新建工程,选择win32 Dynamic link library选项。工程名为:MyFirstDll如下图

    2、选择一个简单的工程,点击完成。

    3、为做简单演示,实现一个两个数相加功能的函数。打开MyFirstDll.cpp文件,添加如下代码extern "C" _declspec(dllexport) int add(int a,int b)

          {

          return a+b;

           }其中extern "C" _declspec(dllexport)不必关心,照写就行。其实这是声明了后面那个add函数是符合C语言规范的一个dll调用接口。后面那个函数就是自己定义的函数。添加之后如下图

          4、点击组建->全部组建就行。

         现在我们的dll问价就做好了,在工程的debug文件夹下面我们发现生成了对应的MyFirstDll.libMyFirstDll.dll文件。怎样使用呢?

    一、静态加载

    很多人编程序都喜欢在程序中静态加载Windows提供的一些库,我们自己生成的库调用方式是一样的。只需添加添加如下代码即可

    #pragma comment(lib,"MyFirstDll.lib")

    extern "C" _declspec(dllexport) int add(int i1,int i2);

    效果如下:

    执行结果如下:

    注意:要将我们生成的MyFirstDll.libMyFirstDll.dll文件拷贝到我们当前工程下,不然是无法运行的。

    二、动态加载

    动态链接的实现方法相当于指针的用法,开始定义一个函数指针,然后找到我们需要的dll文件,然后加载,找到我们需要的函数,将该函数的地址传递给我们定义的函数指针,然后使用我们的函数指针进行操作。函数指针定义如下:

    typedef int(_cdecl* FunctionAdd)(int,int);

    动态加载在需要的时候才加载,采用询问方式进行模拟,询问用户是否加载dll,当用户输入Y之后加载dll文件然后执行。实现如下

    执行效果如下图:

    这样我们自己的dll文件就使用成功了!!!

    展开全文
  • .h头文件 .lib库文件 .dll动态库文件之间的关系

    万次阅读 多人点赞 2013-10-12 11:56:52
    附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。 .h .lib ....

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。

    附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。

    .h .lib .dll三者的关系是:

    H文件作用是:声明函数接口

    DLL文件作用是: 函数可执行代码

    当我们在自己的程序中引用了一个H文件里的函数,编链器怎么知道该调用哪个DLL文件呢?这就是LIB文件的作用: 告诉链接器 调用的函数在哪个DLL中,函数执行代码在DLL中的什么位置,这也就是为什么需要附加依赖项 .LIB文件,它起到桥梁的作用。如果生成静态库文件,则没有DLL ,只有lib,这时函数可执行代码部分也在lib文件中

    目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

    一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。在动态库的情况下,有两个文件,而一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

    -------------------------------------------------------------------------------------

    静态链接库(Lib)与动态链接库(DLL)的区别 

         静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。

    静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。


    “每一个lib文件就是若干函数(假设只有函数)的定义” 
    lib库有两种,一种是包含了函数所在DLL文件和文件中函数位置的信息,称为导出库;一种是包含函数代码本身,一般现有的DLL,用的是前一种库;以前在DOS下的TC/BC等,是后一种库。包含函数原型声明的,是头文件(.h)。 

    “通过#include包含这些函数声明的头文件后,我们的应用程序就可以使用lib文件中的函数”

    还要指定编译器链接相应的库文件。在IDE环境下,一般是一次指定所有用到的库文件,编译器自己寻找每个模块需要的库;在命令行编译环境下,需要指定每个模块调用的库。 

    “那他和直接给出那个函数定义的文件,比如.cpp文件,和头文件有什么区别,静态链接库有什么用” 
    cpp文件是源代码,库文件是编译后的二进制代码,比如你可以调用Windows的API,但是不能看到其源代码一样。 

    “还有不明白的是,静态链接库中的lib文件只要用到,则整个lib文件的内容都放进了exe文件中,那它是被编译进去还是链接的时候连接进去的呢?” 
    是在链接的时候将lib链接到目标代码中。

    静态链接库(Lib)
    在VC++6.0中new一个名称为libTest的static library工程,

    并新建lib.h和lib.cpp两个文件,lib.h和lib.cpp的源代码如下:

    //文件:lib.h
    #ifndef LIB_H
    #define LIB_H
    extern "C" int add(int x,int y);   //声明为C编译、连接方式的外部函数
    #endif

    //文件:lib.cpp
    #include "lib.h"
    int add(int x,int y)
    {
    return x + y;
    }


      编译这个工程就得到了一个.lib文件,这个文件就是一个函数库,它提供了add的功能。将头文件和.lib文件提交给用户后,用户就可以直接使用其中的add函数了。

      标准Turbo C2.0中的C库函数(我们用来的scanf、printf、memcpy、strcpy等)就来自这种静态库。

    下面来看看怎么使用这个库,在libTest工程所在的工作区内new一个libCall工程。libCall工程仅包含一个main.cpp文件,它演示了静态链接库的调用方法,其源代码如下:

    #include <stdio.h>
    #include "..\lib.h"//不可丢失
    #pragma comment( lib, "..\\debug\\libTest.lib" )  //指定与静态库一起连接
    int main(int argc, char* argv[])
    {
         printf( "2 + 3 = %d", add( 2, 3 ) );
    }
      静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白这个概念。代码中#pragma comment( lib , "..\\debug\\libTest.lib" )的意思是指本文件生成的.obj文件应与libTest.lib一起连接

    -------------------------------------------------------------------------------------------

    用VC++生成静态库文件

    今天闲着没事做,自己写了一点小笔记,不知道对于新手有没用,高手就不用看了,作为新手的我斗胆来发表一个笔记,就是静态库文件的封装过程,使用VC++6.0编写,下面是正文,也许我的用语并不专业

    以前我们写C/C++源文件的时候,都是先将各个写好的源文件编译,编译生成的是目标文件机器码,即.obj文件.(目标文件的扩展名不一定是.obj文件).

    我们调用的标准C/C++函数机器码实际被封装于标准C/C++静态库文件中的.即那些扩展名为.lib的文件中.

    最后链接器将我们编译的各个目标文件里的机器码和静态库(标准C/C++库)中的函数机器码链接到一起形成一个扩展名为.exe的可执行文件模块.

    在这里我们叙述将C/C++源文件编译链接成一个静态库文件,但它不是可执行模块,它体内含有可执行机器码

    静态库文件就像一个仓库或者容器,里面封装了一些可执行机器码.这些机器码是我们用程序设计语言,比如C/C++源文件编译后生成的机器码.

    一.下面将讨论将C/C++源文件编译并链接成一个静态库文件的过程,

    在VC++6.0中选择File-New-Win32 Static Library,写好工程名创建好工作空间后再选择菜单中New-File来为工程添加C或者C++ 源文件.

    假如我们为该工程添加了一个名为lib_c.c和一个名为lib_cpp.cpp的源文件

    //lib_c.c中的内容

    extern int Add(int x,int y) //该函数是一个外部函数,任何文件都可以访问它

    {
        return x+y;

    }

    extern int data_c
    //这是一个外部全局变量,任何文件可以访问它

    //lib_cpp.cpp中的内容

    extern “C” int
            reduce(int x,int y)//这里加了个”C”表示允许C源文件访问这个C++函数代码

    {
        return x-y;

    }

    extern “C” int data_cpp=2;

    注意以下几点

    (1)当“extern”关键字修饰在函数或全局变量的定义中时,表示该函数或全局变量任何文件可以访问,“extern”关键字可以省略不写,缺省下就是”extern”

      当“extern”关键字修饰在函数声明或全局变量声明中时,表示限定当前文件只能引用用“extern”关键字修饰定义的函数或全局变量.

    (2)当”static”关键字修饰在函数或全局变量的定义中时,表示该函数或全局变量只能由本文件中加了”static”关键字修饰的函数声明或全局变量声明来引用.

      当”static”关键字修饰在函数声明或全局变量声明中时,表示限定当前文件只能引用用“static”关键字修饰定义的函数或全局变量.

    (3)在CPP源文件的函数和全局变量定义中加了个”C”表示允许C源文件访问该函数和全局变量.如果是C++源文件访它们的话则可加可不加.注意这”C”要大写.

    接下来就要将写好的C/C++源文件进行编译和链接,最后会生成一个扩展名为.lib的文件.该文件就是静态库文件了,该静态库文件是不能直接运行的,我们所编译的C/C++源文件的机器码就已经被封装进这个用VC++6.0创建的静态库文件里面去了.

    二.如何将编写好的静态库文件像使用C/C++标准库那样使用,下面将继续讨论

    1.用VC++6.0新建一个工程名为TEST,添加一个名为TEST.c的源文件到该工程,因为我们将测试一下,将我们编写的库文件里的函数或者全局变量的机器码链接到我们这个TEST.c源文件中去,假设我们生成的库文件名为TEST.lib,先拷贝如下范例代码到TEST.c中

    //TEST.c

    #include <stdio.h>

    extern int 
    Add(int x,int y); //当前文件只能访问“extern”关键字修饰定义的Add函数

    extern int
    reduce(int x,int y);// //当前文件只能访问“extern”关键字修饰定义的reduce函数

    #pragma comment(lib,"TEST.lib") //指示链接器到字符串所表示的文件路径中去找库文件

    int main()

    {
        printf("%d\n",Add(2,3));

        printf("%d\n",reduce(3,2));

        return 0;

    }

    这里我们要声明静态库中已知的函数或全局变量的声明

    #pragma comment(lib,"TEST.lib")这条指令告诉链接器到字符串所表示的路径下去找库文件,这里我将库文件放到了当前工程目录下.也可以不写这句.

    还有一种方法,可以直接在VC++6.0中设置依次选择toolsoptionsdirectorieslibrary files菜单或选项,填入库文件路径(只键入库文件所在目录路径而不能输入库文件名),这只是告诉链接器库文件所在目录的路径,还没告诉链接器库文件名,方法是VC++6.0中设置依次选择project-settings-link 在object/library modules: 这栏输入库文件名字然后就OK了

    2.当用C++源文件的目标文件和库文件的代码链接时有一点小改变,这里就不浪费口舌了,假设我们新建了一个工程并添加了一个名为TEST.CPP的源文件,拷贝如下范例代码到TEST.CPP中

    //TEST.cpp

    #include <stdio.h>

    extern “C” int 
           Add(int x,int y); //表示引用的是C函数代码

    extern int
          reduce(int x,int y);

    #pragma comment(lib,"TEST.lib")

    int main()

    {
        printf("%d\n",Add(2,3));

        printf("%d\n",reduce(3,2));

        return 0;

    }

    在这个C++源文件里引用C函数代码同样要加个”C”,但是在C源文件引用C++函数代码不能加”C++”,编译会报错,只能在C++文件函数定义中加”C”.

    只有C++才支持这种引用方式,也许因为只有C++兼容C而没有C兼容C++这一原则.




    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。

    附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。

    .h .lib .dll三者的关系是:

    H文件作用是:声明函数接口

    DLL文件作用是: 函数可执行代码

    当我们在自己的程序中引用了一个H文件里的函数,编链器怎么知道该调用哪个DLL文件呢?这就是LIB文件的作用: 告诉链接器 调用的函数在哪个DLL中,函数执行代码在DLL中的什么位置,这也就是为什么需要附加依赖项 .LIB文件,它起到桥梁的作用。如果生成静态库文件,则没有DLL ,只有lib,这时函数可执行代码部分也在lib文件中

    目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

    一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。在动态库的情况下,有两个文件,而一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

    -------------------------------------------------------------------------------------

    静态链接库(Lib)与动态链接库(DLL)的区别 

         静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。

    静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。


    “每一个lib文件就是若干函数(假设只有函数)的定义” 
    lib库有两种,一种是包含了函数所在DLL文件和文件中函数位置的信息,称为导出库;一种是包含函数代码本身,一般现有的DLL,用的是前一种库;以前在DOS下的TC/BC等,是后一种库。包含函数原型声明的,是头文件(.h)。 

    “通过#include包含这些函数声明的头文件后,我们的应用程序就可以使用lib文件中的函数”

    还要指定编译器链接相应的库文件。在IDE环境下,一般是一次指定所有用到的库文件,编译器自己寻找每个模块需要的库;在命令行编译环境下,需要指定每个模块调用的库。 

    “那他和直接给出那个函数定义的文件,比如.cpp文件,和头文件有什么区别,静态链接库有什么用” 
    cpp文件是源代码,库文件是编译后的二进制代码,比如你可以调用Windows的API,但是不能看到其源代码一样。 

    “还有不明白的是,静态链接库中的lib文件只要用到,则整个lib文件的内容都放进了exe文件中,那它是被编译进去还是链接的时候连接进去的呢?” 
    是在链接的时候将lib链接到目标代码中。


    展开全文
  • 当我们需要生成静态链接lib文件、动态链接库dll文件,都需要在工程路径中找到,比如在Debug文件中,但有时候会出现写好文件编译生成时,在Debug文件下找不到想要的文件,自然也就无法调用或者时查看里面的函数类型...
  • ...附加依赖项的是.lib不是.dll,若生成了dll,则肯定也生成lib文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果要使需要动态连接的程序运行起来,有dll就够了。在开发和调试阶
  • 无法定位dll文件程序输入点

    千次阅读 2018-04-19 16:02:53
    一般来说都是dll库不对,或者是DLL库不全,还有其他的DLL文件没有加进C:\Windows\SysWOW64中。
  • dll动态链接库文件编写

    万次阅读 多人点赞 2017-12-02 20:50:52
    1.动态链接dll)概述 没接触dll之前觉得它很神秘,就像是一个黑盒子,既不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其他dll调用来完成某项工作的函数,只有在其他模块...
  • 本文章收藏了关于PHP命令行模式提示”没有找到php_mbstring.dll文件无法启动”多种解决办法,有需要的朋友可以参考一下。 解决方法: 在php.ini文件中将 extension=php_mbstring.dll 移动到 extension=...
  • 经常遇见同事电脑出现,excel 无法找到入口 enumcalendarInfoExEx 于动态链接KERNEL32.DLL; 在百度中检索很久,发现大多数解决方案,并不能解决该问题。 有一次在找资料的过程中,发现该解决方案;下面提供...
  • DLL文件即动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows提供的DLL文件中包含了允许基于Windows的程序在Windows环境下操作的许多函数和资源。  DLL多数情况下是...
  • 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。 .h ....
  • fatal error C1083: 无法打开类型库文件:“msado15.dll” 提示无法打开msado15.dll,需要在安装目录下找到msado15.dll放到debug目录下即可
  • 在调试阶段总是找不到一些动态连接,提示“错误 52 XX.dll 文件找到 ”。 将dll放进system32或者把调试目录加入path都可以解决这个问题,但是,这不是我想要的。 最后,用尽浑身解数找到答案: 将dll们删除 ...
  • mfc42d.dll是MFC DLL共享库文件,用于支持调试版本的MFC程序。 mfc42d.dll下载地址:http://www.zhaodll.com/search.asp?word=mfc42d_dll 一、用户: a、去找个MFC42.DLL 拷贝过去C:\WINDOWS\system32 二、...
  • 无法找到所需的动态链接库或其他文件 AcRxDynamicLinker 出现该问题有可能是: ...2、加载的文件还需要以来的其他库文件先加载,需要检查,然后修改调整顺序。 3、还有可能是分为32与64使用错误。...
  • VS2013 动态编译无法启动***.dll文件

    千次阅读 2017-08-03 11:37:40
    新手学习,需要编译动态时经常碰到无法启动***.dll的问题,这个主要是运行程序后,没有清理解决方案。只要在菜单项点击“生成”->“清理解决方案”,然后重新运行就可以了。而动态的测试就需要另建项目调用...
  • windows DLL动态连接库文件的实现和应用动态连接库文件dll文件(windows下,linux下为.so文件),里面其实为已经实现的函数库,可以随时导入为多个程序同时使用。它实现时就被编译了,所以它实质是一种不可执行的...
  • 批量注册修复动态链接 DLL 文件

    千次阅读 2011-08-23 15:14:39
    所有 DLL 文件一般都在 system32 目录下,如果能把 system32 目录下所有 DLL 文件都注册一下,那么不就...怎么才能3秒钟找到 DLL 文件的“罪魁祸首”,把 system32 目录下的所有DLL 文件都注册一遍呢?
  • dll文件无法打入jar包,dll文件位置是相对路径 打包项目之后就调用不到dll文件 但是程序运行需要调用dll文件来完成功能 解决办法 将调用dll文件的方法由相对路径改为绝对路径 //例如调用海康摄像头中的一个地方//...
  • 工程在release模式下可以编译成功,但是运行总是出现无法找到msvcp90.dll的错误。在我的机器上编译和运行都没有问题。我用depends打开exe文件,使用全路径来查看依赖,发现确实找不到msvcp90.dll(同事的VS 2008...
  • ///使用法方: ///一、添加dll文件到资源里(项目-》右键-》属性-》资源-》文件-...///三、在引用里右键-》添加引用-》找到你添加到Resources文件夹里的dll文件,并在属性里,复制本地,设置为false。/// ///四、在Pr
  • 首先我们先来学习一下动态的调用,先找到动态的.dll和.lib文件并将其导入到同源文件相同级别的文件夹下面,然后在添加进其头文件,并右击项目处,然后点击链接,链接我们的lib文件(一定要是全名称包括扩展名)...
  • 一、几种文件的作用 h头文件作用:声明函数接口 dll动态链接作用:含有函数的可执行代码 lib有两种: (1)静态链接(Static Libary,以下简称“静态”) (2)动态连接(DLL,以下简称“动态”)的导...
  • “RegSvr32 已加载mshtml.dll,但没有找到DllRegisterServer输入点。无法注册这个文件。”解决办法全集 办法一:对于那些可以自行注册的对象链接和嵌入 (OLE) 控件,例如动态链接 (DLL) 文件或 ActiveX ...
  • 一、静态和动态1、静态(.lib) 函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态的情况下,在编译链接可执行文件时,链接器从中复制... 2、动态(.lib文件和.dll文件) 在使用动态
  • 最近做一个项目,需要在WEB端上传文件并打zip包,供...而c#的FileInfo类获取到的文件修改时间是精确到微秒,而且这两个时间在微秒的取舍上并没有四舍五入、逢余进一等规律,所以自己用C#编写了一个dll库,提供C#的文件

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 95,883
精华内容 38,353
关键字:

无法找到dll库文件