dynamic link library --load-time dynamic linking

//dll project

.h

View Code
#ifdef DLL_TEST1_EXPORT
#define DLL_DECLSPEC __declspec(dllexport)

#else
#define DLL_DECLSPEC __declspec(dllimport)
#endif


extern "C" DLL_DECLSPEC int WINAPI Add(int, int);

DLL中导出函数的声明有两种方式:

一种为4.1节例子中给出的在函数声明中加上__declspec(dllexport),这里不再举例说明;

另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。

.cpp .def

View Code
#include <Windows.h>
#include <stdio.h>

#define  DLL_DECLSPEC

#include "DllTest1.h"



 BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
            printf("attached\n");
            break;

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
            break;
    }
            return TRUE;
 }


 int WINAPI Add(int a, int b)
 {
     return a + b;
 }

入口函数

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )  // reserved

Calling the Entry-Point Function

The system calls the entry-point function whenever any one of the following events occurs:

 

  • A process loads the DLL. For processes using load-time dynamic linking, the DLL is loaded during process initialization. For processes using run-time linking, the DLL is loaded before LoadLibrary or LoadLibraryEx returns.
  • A process unloads the DLL. The DLL is unloaded when the process terminates or calls the FreeLibrary function and the reference count becomes zero. If the process terminates as a result of the TerminateProcess or TerminateThread function, the system does not call the DLL entry-point function.
  • A new thread is created in a process that has loaded the DLL. You can use the DisableThreadLibraryCalls function to disable notification when threads are created.
  • A thread of a process that has loaded the DLL terminates normally, not using TerminateThread or TerminateProcess. When a process unloads the DLL, the entry-point function is called only once for the entire process, rather than once for each existing thread of the process. You can use DisableThreadLibraryCalls to disable notification when threads are terminated.

Only one thread at a time can call the entry-point function.

The system calls the entry-point function in the context of the process or thread that caused the function to be called. This allows a DLL to use its entry-point function for allocating memory in the virtual address space of the calling process or to open handles accessible to the process. The entry-point function can also allocate memory that is private to a new thread by using thread local storage (TLS). For more information about thread local storage, see Thread Local Storage.

Entry-Point Function Definition

The DLL entry-point function must be declared with the standard-call calling convention. If the DLL entry point is not declared correctly, the DLL is not loaded, and the system displays a message indicating that the DLL entry point must be declared with WINAPI.

 

The entry-point function should perform only simple initialization tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code. Similarly, the entry-point function must not call the FreeLibrary function (or a function that calls FreeLibrary) during process termination, because this can result in a DLL being used after the system has executed its termination code.

Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can create synchronization objects such as critical sections and mutexes, and use TLS, because these functions are located in Kernel32.dll. It is not safe to call the registry functions, for example, because they are located in Advapi32.dll.

Windows 2000: Do not create a named synchronization object in DllMain because the system will then load an additional DLL. This restriction does not apply to subsequent versions of Windows.

 

Calling other functions may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions in their DLLs call LoadLibrary to load other system components. Conversely, calling those functions during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.

View Code
LIBRARY "DllTest1"

EXPORTS Add @1

.def文件的规则为:

  (1)LIBRARY语句说明.def文件相应的DLL

  (2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

  (3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。

  (4) .def 必须有LIBRARY 和EXPORTS

 

//app project 

 

View Code
#include <Windows.h>

#include <stdio.h>
#include "..\\dllmain\DllTest1.h"
#pragma comment(lib, "..//release//DllTest1.lib")

//extern "C" __declspec(dllimport) int WINAPI Add(int, int);



int main()
{

    printf("4 + 6 = %d\n", Add(4, 6));
    

    return  0;
}

由上述代码可以看出,静态调用方式的顺利进行需要完成两个动作:

 

  (1)告诉编译器与DLL相对应的.lib文件所在的路径及文件名,#pragma comment(lib,"dllTest.lib")就是起这个作用。

  程序员在建立一个DLL文件时,连接器会自动为其生成一个对应的.lib文件,该文件包含了DLL 导出函数的符号名及序号(并不含有实际的代码)。在应用程序里,.lib文件将作为DLL的替代文件参与编译。

  (2)声明导入函数,extern "C" __declspec(dllimport) add(int x,int y)语句中的__declspec(dllimport)发挥这个作用。

posted on 2013-02-25 01:08  All IN  阅读(298)  评论(0)    收藏  举报

导航