VisualStudio makes Dynamic Link Library dynamic link library files

Dynamic Link Library dynamic link library file


Toolset

With the help of tools, the access address of Dll library functions can be obtained. The following two tools are recommended for use:

how to generate

__declspec(dllexport)

Declaring a function as an exported function means that this function will be called by other programs, that is, as an external function interface of the DLL.

__declspec(dllexport) RETURN_TYPE FUNCTION()

extern “C”

Due to the existence of function overloading due to C++ when making a DLL export function

  • Therefore, __declspec(dllexport) FUNCTION(int,int)the DLL will be decorated, for example: be decorated as function_int_int,
  • Moreover, different compilers have different decorate methods, which causes inconvenience when GetProcAddressusingFUNCTION地址
  • When used extern "C", the above decorate will not happen, because C does not have function overloading, so 被extern"C"修饰的函数,就不具备重载能力.
extern "C" {
    
    
  __declspec(dllexport) RETURN_TYPE FUNCTION(){
    
    
    ;
  }
}

how to use

  • The dynamic loading method means that before compiling, it does not know which DLL functions will be called, and it is completely determined which functions should be called during the running process according to the needs.
  • The method is: use the LoadLibrary function to load the dynamic link library to the memory, and use the GetProcAddress function to dynamically obtain the entry address of the DLL function.
  • When a DLL file is explicitly loaded with LoadLibrary, it can be unloaded from memory explicitly by calling the FreeLibrary function at any time.
  • There are three main Windows API functions used by dynamic calls, namely LoadLibrary, GetProcAddressandFreeLibrary

statement call

Pay attention to the DLL function calling convention, which must be consistent

  1. __stdcallWindows API default function call protocol
  2. __cdeclC/C++ default function call protocol
  3. __fastcallSuitable for occasions with high performance requirements

Example

  1. Suppose I have a functional interface as follows:

    //@ GETCOMCHECKSUM_API是一个宏定义
    //@ #define GETCOMCHECKSUM_API __declspec(dllexport)
    GETCOMCHECKSUM_API int fnGetComCheckSum(
                            const unsigned char*  iCsArray,       //[In]数组
                            const unsigned int    iCsSize,        //[In]数值
                            unsigned char&        ioCsValue)      //[In/Out]数值
    
  2. Then my call should be written like this:

    //@ __cdecl * 后面函数名可以自定义
    typedef int(__cdecl *GetComCheckSum)(
                unsigned char const *,
                unsigned int,
                unsigned char&);
    

LoadLibrary

  1. [format] function LoadLibrary(LibFileName : PChar): Thandle;
  2. [Function] Load the DLL file specified by the parameter LibFileName
  3. [Description] The parameter LibFileName specifies the name of the DLL file to be loaded
    • If LibFileName does not contain a path, the system will look for the file in the following order: the current directory, the Windows directory, the Windows system directory, the directory containing the executable for the current task, the directories listed in the PATH environment variable, and so on.

If the function operation is successful, it will return the instance handle of the loaded DLL library module, otherwise, it will return an error code, the definition of the error code is shown in the following table

错误代码             含义
      0             系统内存不够,可执行文件被破坏或调用非法
      2             文件没有被发现
      3             路径没有被发现
      5             企图动态链接一个任务错误或者有一个共享或网络保护错误
      6             库需要为每个任务建立分离的数据段  
      8             没有足够的内存启动应用程序  
      10            Windows  版本不正确  
      11            可执行文件非法或不是Windows  应用程序,或在.  EXE映像中有错误  
      12            应用程序为一个不同的操作系统设计(如  OS/2)  
      13            应用程序为  MS  DOS   4. 0  设计  
      14            可执行文件的类型不知道  
      15            试图装载一个实模式应用程序(为早期Windows  版本设计)
      16            试图装载包含可写的多个数据段的可执行文件的第二个实例  
      19            试图装载一个压缩的可执行文件(文件必须被解压后才能被装载)  
      20            DLL  文件非法
      21            应用程序需要  32  位扩展

Example

//@ 定义句柄
HINSTANCE hSnKLib;

//@ 获取链接库句柄       Getchecksum为dll的文件名 即 Getchecksum.dll
//@ 系统将会在当前目录下寻找名为Getchecksum.dll的文件
//@ 至于为什么使用_T("") ,_T是一个宏,作用是让你的程序支持Unicode编码,Windows使用两种字符集ANSI和UNICODE
hSnKLib = LoadLibrary(_T("Getchecksum"))

//@ 如果未能成功获取,抛出错误
if (hSnKLib == NULL)
{
    
    
    FreeLibrary(hSnKLib);
  	printf("LoadLibrary err\n");
  	getchar();
  	return 1;
}

GetProcAddress

  1. Format:function GetProcAddress(Module:Thandle; ProcName:PChar): TfarProc;
  2. Function: Return the entry address of the procedure or function specified by the parameter ProcName in the module specified by the parameter Module
  3. Explanation: The parameter Modulecontains the DLL handle of the called function. This value is returned by LoadLibrary. procNameIt is a pointer to a nil-terminated string containing the function name, or it can be the sequence value of the function.
    • In most cases, using 函数名is a safer choice.
    • If the function is executed successfully, it returns the procedure specified by the parameter ProcName in the DLL or 函数的入口地址, otherwise, it returns nil.

Example

//前面我们在头文件中声明了下述函数
typedef int(__cdecl *GetComCheckSum)(
            unsigned char const *,
            unsigned int,
            unsigned char&);


//实例化并且获取函数地址
//fnGetComCheckSum为dll export出来的函数名,GetComCheckSum为我们引用时候声明的函数名
//这里做的工作就是将dll中函数与我们声明的联系到一块。
GetComCheckSum getcom = (GetComCheckSum)GetProcAddress(hSnKLib, "fnGetComCheckSum")

if (!getcom)
{
    
    
	FreeLibrary(hSnKLib);			//释放dll文件
	//Add your code here
}

FreeLibrary

  1. Format:procedure FreeLibrary(Module: Thandle);
  2. Description: Unload the DLL file specified by the parameter Module from memory once.
  3. Description: Module is the handle of the DLL library. This value is returned by LoadLibrary. Since the DLL is only loaded once in memory, calling FreeLibrary first decrements the reference count of the DLL by 1, and unloads the DLL if the count is reduced to 0
  4. Note: The FreeLibrary function should be called every time the LoadLibrary function is called to ensure that no redundant library modules remain in the memory after the application ends, otherwise memory leaks will result.

Example

FreeLibrary(hSnKLib);




FAQS

Question 1: GetLastError gets error code 127

Problem Description:

  1. Use "during runtime dynamic link" own dll file
  2. LoadLibrary successfully obtains the dll module handle
  3. But GetProcAddress(hModule, "ExportFunc") returns NULL, and GetLastError gets error code 127, which means "the specified program cannot be found"

identify the problem:

  1. Use the Depends tool (VS2010 does not have it by default, you need to download it separately: http://www.dependencywalker.com/) to check the name of the exported function of the dll.
  2. It is found that the export function name is no longer "ExportFunc", but "decorate" according to the return type and parameters of the function, and becomes "?ExportFunc@@YAXPB_W@Z".

There are two solutions:

  1. Modify the second parameter of GetProcAddress to the real export function name

  2. Add the DEF file in the dll project and write the following content:

    EXPORTS
                   ExportFunc
    
    • Recompile the dll project. Use the Depends tool again to view the name of the exported function, which is "ExportFunc".
    • Project – linker – in the input module definition file, add your own DEF file
      insert image description here




References

Guess you like

Origin blog.csdn.net/qq_33704787/article/details/126090055