zoukankan      html  css  js  c++  java
  • Lib和Dll的那点事

    搞程序开发的朋友应该对LibDll很熟悉,对于这两个东西,可谓是几家欢喜几家忧,喜欢的人觉得它可以封装代码,避免别人剽窃,不喜欢的人觉得它很麻烦,干嘛不直接用源文件。而特别是新手对于LibDll的关系和使用完全搞不清楚。

    Lib称为静态链接库(static link library),是在编译的链接期间使用的,他里面其实就是源文件的函数实现。

    Dll成为动态链接库(Dynamic link library),是在程序运行时动态调用的,runtime时使用,它里面包含了源文件的函数实现、DllMain入口函数和.def文件。

    先说说Lib库吧,相对来说大家对它比dll熟悉一些。

    Lib库

    Lib库有两种,一种就是常见的普通Lib(static Lib),还有一种大家经常下载的开源代码编译后,会产生Lib和dll,其中Lib只是Dll的附带品,是DLL导出的函数列表文件而已,暂且称之为Dynamic Lib

    两者都是二进制文件,两者都是在链接是调用的,使用static lib的exe可直接运行,使用dynamic lib的exe需要对应的dll才能运行。下来我们来看如何产生并使用一个static lib文件。

    这里假设我们的工具是VS2005(包含)以上的版本,其他的工具都是大同小异的,就不做介绍了。

    1.建立win32控制台工程

    2.在应用程序设置的步骤,选择”静态库 static Library”

    3.完成即可 (这里只是针对最简单的Dll,Win32 Application的方式稍有不同)

    这样一个静态Lib库的工程就建好了。代码如下:

    //////////////////////////////////////////////////////////////////////////
    // Function.h
    //////////////////////////////////////////////////////////////////////////
    
    void Print();
    //////////////////////////////////////////////////////////////////////////
    // Function.cpp
    //////////////////////////////////////////////////////////////////////////
    #include "Function.h"
    
    void Print()
    {
    	std::cout << "Hello world!" << std::endl;
    }

    编译会生成一个以工程名作为名称的Lib文件。

    在你的项目工程属性中包含这个Lib文件的头文件目录和Lib文件目录。

    头目录包含方法:项目属性(Alt + F7) -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录,里面包含你的Lib库的头文件,你可以使用绝对路径,也可以使用VS中宏表示的相对路径,建议使用相对路径。

    Lib文件包含方法:项目属性(Alt + F7) -> 配置属性 -> 链接器 -> 常规 -> 附加库目录,在这里面填写你Lib文件的路径。项目属性(Alt + F7) -> 配置属性 -> 链接器 -> 常规 -> 输入,在这里面填写你Lib文件的名称,例如: Function.lib

    这样你在你的代码里就可以这样使用了:

    #include <stdio.h>
    #include <stdlib.h>
    #include "Function.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	Print();
    	system("pause");
    	return 0;
    }

    这样就是一个完整生成并使用Lib库的例子。

    当然了,你还可以使用#pragma comment(Lib, “LibPath”)的方法来调用Lib文件。

    ==============================================================

    Dynamic Lib的调用方法与Static lib完全一致,唯一的区别就是使用Dynamic Lib编译出来的程序,运行时需要其对应的Dll文件。前面我们已经说过了。

    DLL

    下来我们好好谈谈Dll的问题,相对于Lib来说,Dll使用的频率应该是非常高的了,因为你的程序运行,系统运行等等都靠它,MS也是因为这个才导致操作系统封装的越来越好了。

    Dll其实和Exe是几乎完全一样的,唯一的不一样就是Exe的入口函数式WinMain函数(console程序是main函数),而Dll是DllMain函数,其他完全是一样的。所以有人也戏称Dll是不能自己运行的Exe。

    Dll创建的过程也比较简单,唯一麻烦的就是需要定义导出函数接口。

    创建Dll工程过程很简单,建立win32控制台工程,在应用程序设置的步骤,选择”动态库 Dynamic Library”,完成即可。(这里只是针对最简单的Dll,Win32 Application的方式稍有不同)

    定义导出函数接口有两种方式:

    1.使用__declspec宏

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "stdafx.h"
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
    //////////////////////////////////////////////////////////////////////////
    // Fucntion.h
    //////////////////////////////////////////////////////////////////////////
    
    extern "C" __declspec(dllexport) void Print(void);
    //////////////////////////////////////////////////////////////////////////
    // Function.cpp
    //////////////////////////////////////////////////////////////////////////
    #include "Function.h"
    
    void Print(void)
    {
    	std::cout << "[Dll] Hello world!" << std::endl;
    }

    这里假设我们的工程名叫Function,那么 编译后会生成一个Function.dll和一个Function.lib(Dynamic lib),Dynamic lib前面已经说过,此处不再赘述了。

    Function.h头文件中的

    extern "C" __declspec(dllexport) void Print(void);

    我们只需要清楚其中函数的名称,返回值,参数就可以了。

    extern “C”表示我们要按照C语言的方式编译该函数,防止在C++工程中编译出现函数名错误,因为C++中有函数重载,所以函数名编译后可能会出现Print@1的形式;而且这样也可以让C调用C++的动态链接库;__declspec(dllexport)表示下来的函数是dll的导出函数接口。

    2.使用def文件,类似于声明导出接口的方式,不过却不需要声明了,因为它专门定义了一个def文件来说明

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "stdafx.h"
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
    //////////////////////////////////////////////////////////////////////////
    // Fucntion.h
    //////////////////////////////////////////////////////////////////////////
    
    void Print(void);
    //////////////////////////////////////////////////////////////////////////
    // Function.cpp
    //////////////////////////////////////////////////////////////////////////
    #include "Function.h"
    
    void Print(void)
    {
    	std::cout << "[Dll] Hello world!" << std::endl;
    }
    //////////////////////////////////////////////////////////////////////////
    // Fucntion.def
    //////////////////////////////////////////////////////////////////////////
    
    EXPORTS
    	Print

    同样,类似于Static Lib的显式调用方法,dll也可以显式调用,前提是我们很清楚函数名、返回值、参数列表。

    #include <stdlib.h>
    #include "Function.h"
    #include <windows.h>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        HINSTANCE hInstance  = LoadLibrary("Function.dll");
        typedef void(*_Print)(void);
        _Print printFunction;
        if (hInstance != NULL)
        {
            printFunction = (_Print)GetProcAddress(hInstance, "Print");
        }
    
        printFunction();
        FreeLibrary(hInstance);
        system("pause");
        return 0;
    }

    当然了,有显式自然还有隐式调用了,这个时候Function.dll的伴生产物Function.lib就可以派上用场了,其使用方法和静态lib完全相同。

    DLL调用的两种方法各有利弊:采用寻找DLL中函数地址的方法,优点是只要函数形参没变化,那么修改了函数实现也没关系,不需要重新编译Exe,只需要将新的DLL文件拷贝过来即可,大型项目上使用比较灵活;缺点是比较麻烦,需要定义实例,函数指针,加载DLL,释放DLL等过程。而采用Dynamic Lib的方法,优点是容易理解和接受(因为他跟静态库的调用方法类似);缺点是修改了DLL工程的任何东西都需要使用最新的Dynamic Lib重新能编译Exe。

    总结:

    DLL和Lib是各有千秋,使用的情况也是各不相同,不过最终还是需要大家在项目中实践到底哪种方法好,到底采用哪种类型的库,总之,一切都要按需求最优。

  • 相关阅读:
    【svn】一个设置,少写几个字
    转眼一年
    linux虚拟机与windows主机传输文件方法
    meta常用命令
    Metasploit 读书笔记-持久控制
    Metasploit 读书笔记-神器Meterpreter
    [工作]采购失误
    解决:kali linux 在vmware 虚拟机中使用bridge模式上网的问题
    metasploit 读书笔记-EXPLOITATION
    [共鸣]温州600住户合买高音炮 还击广场舞大妈
  • 原文地址:https://www.cnblogs.com/zwei1993/p/4598027.html
Copyright © 2011-2022 走看看