DLL显式载入

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/delongwang520/article/details/79318948

之前在文章中提到 过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的映射。
运行结果如下:

这里写图片描述

展开阅读全文

显式连接DLL的问题

04-18

我写了一段小程序,里面有一个addxy的函数,用于计算x,y的和。我把这段程序生成了一个add.dllrn之后又写了一段代码,用显式的方法调用这个DLL文件,不过用显式的方法调用时一直没成功,hDll = LoadLibrary(LPCWSTR("add.dll"))的返回值一直是0,调用getlasterror得到126----找不到指定模块!DLL文件的位置没有问题,我试过多次了,也写过绝对路径。而且我换成调用系统的Kernel32.dll文件也是返回0,麻烦各位大虾帮我看一下是什么原因,小弟感激不尽!!rnrn刚注册的,还没有积分,望见谅!rnrn//以下是生成DLL程序的主要代码rn// add.cpp : 定义 DLL 应用程序的入口点。rn//rnrn#include "stdafx.h"rnrnrn#include rn#include rn#include rnrnrn//#if BUILDING_DLLrn# define DLLIMPORT __declspec (dllexport)rn//#else /* Not BUILDING_DLL */rn//# define DLLIMPORT __declspec (dllimport)rn//#endif /* Not BUILDING_DLL */rnrn/*定义了一个 dll 函数 addxy,返回2个数的和*/rnextern "C" DLLIMPORT int addxy ( int x, int y)//---此处要加extern "C"吗rnrn return (x+y);rnrnrnrnBOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,rn DWORD reason /* Reason this function is being called. */ ,rn LPVOID reserved /* Not used. */ )rnrn switch (reason)rn rn case DLL_PROCESS_ATTACH: /*dll 进程加载的时候执行的事情*/rn break;rnrn case DLL_PROCESS_DETACH: /*dll 进程卸载的时候执行的事情*/rn break;rnrn case DLL_THREAD_ATTACH: /*dll 线程加载的时候执行的事情*/rn break;rnrn case DLL_THREAD_DETACH: /*dll 线程卸载的时候执行的事情*/rn break;rn rnrn /* Returns TRUE on success, FALSE on failure */rn return TRUE;rnrnrnrn//以下是调用DLL的程序代码rn#include "stdafx.h"rnrn#include rn#include rn#include rnrnextern "C" //-----此处要加吗rnrnrntypedef int(*lpAddFun)(int, int); //宏定义函数指针类型rnrnint main(int argc, char *argv[])rnrn HINSTANCE hDll; //DLL句柄rn lpAddFun addFun; //函数指针rn int result;rnrn rn SetLastError(0);rn hDll = LoadLibrary(LPCWSTR("add.dll")); /*加载 testdll.dll*/rn //hDll = ::LoadLibrary((LPCTSTR)"Kernel32.dll");rn int err = GetLastError();rn if (hDll != NULL)rn rn addFun = (lpAddFun)GetProcAddress(hDll, "addxy");rn if (addFun != NULL)rn rn result = addFun(654, 212); /* 654 + 212*/rn rn FreeLibrary(hDll);rn rn return 0;rnrnrn以下是隐式调用部分,在环境中设置了add.librn//__declspec(dllimport) int addxy(int,int);rn//rn//int main(int argc, char *argv[])rn//rn// int z = addxy(3,5);rn//rn 论坛

没有更多推荐了,返回首页