DLL显式载入

之前在文章中提到 过DLL的隐式链接,现在介绍以下DLL的显式载入。DLL显式载入与隐式链接不同的是,我们不需要包含包含DLL导出函数和变量的头文件,不需要显式指定lib文件,比如以下两行代码就可以去掉了。

#include "userdefine.h"
#pragma comment(lib,"userdefine.lib")

上代码:

//userdefine.h
#ifdef USERDEFINE_EXPORTS
#define USERDEFINE_API extern "C" __declspec(dllexport)
#else
#define USERDEFINE_API extern "C" __declspec(dllimport)
#endif


USERDEFINE_API int fnuserdefine(void);

USERDEFINE_API int g_nResult;//尽量避免导出变量
//userdefine.cpp
#define USERDEFINE_API extern "C" __declspec(dllexport)

#include "userdefine.h"
#include <tchar.h>

int g_nResult;

int fnuserdefine(void)
{
    g_nResult = 256;
    _tprintf(_T("DLL test example\n"));
    return g_nResult;
}
//FirstThread
CRITICAL_SECTION g_cs;
UINT WINAPI FirstThread(PVOID pvParam)
{
    EnterCriticalSection(&g_cs);
    g_num = 0;
    for (int  i = 0; i <= COUNT; i++)
    {
        g_num += i;
    }
    _tprintf(_T("FirstThread g_num=%d TheadID= %d\n"), g_num, GetCurrentThreadId());
    LeaveCriticalSection(&g_cs);
    return g_num;
}
//dllmain.cpp
#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
// Windows 头文件: 
#include <windows.h>
#include <tchar.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        _tprintf(_T("DLL_PROCESS_ATTACH\n"));
        break;
    case DLL_THREAD_ATTACH:
        _tprintf(_T("DLL_THREAD_ATTACH\n"));
        break;
    case DLL_THREAD_DETACH:
        _tprintf(_T("DLL_THREAD_DETACH\n"));
        break;
    case DLL_PROCESS_DETACH:
        _tprintf(_T("DLL_PROCESS_DETACH\n"));
        break;
    default:
        break;
    }
    return TRUE;
}
//main.cpp
typedef int (CALLBACK *PFN_USERDEFINE)(void);

int _tmain( int argc, TCHAR* argv[] )
{
    HMODULE hmodule = GetModuleHandle(_T("userdefine"));
    if (NULL == hmodule)
    {
        hmodule = LoadLibrary(_T("userdefine"));
    }
    if ( NULL == hmodule)
    {
        _tprintf(_T("Can not find dynamic library\n"));
        return -1;
    }

    PFN_USERDEFINE pfnUserDefine = (PFN_USERDEFINE)GetProcAddress(hmodule, "fnuserdefine");
    if ( NULL != pfnUserDefine )
    {
        int nRet = pfnUserDefine();
        _tprintf(_T("nRet=%d\n"), nRet);
    }
    InitializeCriticalSection(&g_cs);//初始化关键段
    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, FirstThread, NULL, 0, NULL);

    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    DeleteCriticalSection(&g_cs);
    FreeLibrary(hmodule);

dllmain函数是dll入口点处理函数,可以处理进程(或线程)加载dll的时候或者进程(或线程)退出时,dll需要做的工作。
GetModuleHandle函数是判断userdefine.dll有没有被加载,如果没有被加载,那么调用LoadLibrary函数加载dll。我们定义一个PFN_USERDEFINE函数指针,该函数指针的原型就是我们需要调用dll函数的原型,如果成功找到了这个函数,那么我们调用该函数获取其返回值。创建一个线程运行FirstThread函数,线程创建退出时,DLL会得到通知并打印相应信息,最后通过FreeLibrary函数从该进程的地址空间间取消对该Dll的映射。
运行结果如下:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值