zoukankan      html  css  js  c++  java
  • 编写DLL

    想想还是把这个记录下吧,虽然不难,但由于平时写得不多,老是搞忘了。

    1、我们来编写一个简单的DLL程序。

    首先,我们来看下入口函数DllMain()。DllMain()有3个参数:

    (1)hModule:DLL模块的句柄。

    (2)ul_reason_for_call:DllMain函数被调用的原因。其取值有4种,分别是DLL_PROCESS_ATTACH(当DLL被某进程加载时DllMain被调用)、DLL_PROCESS_DETACH(当DLL被某进程卸载时DllMain被调用)、DLL_THREAD_ATTACH(进程中有线程被创建时DllMain被调用)、DLL_THREAD_DETACH(进程中有线程结束时DllMain被调用)。

    (3)lpReserved:保留项。

    函数前面的APIENTRY是一个宏,定义如下:

    #define APIENTRY    WINAPI

    WINAPI也是一个宏,表示一种函数调用约定。

    我们需要对DllMain()进行一下填充,加个switch。后面详见例子。我们还需要为之添加一个简单的导出函数。该函数定义如下:

    extern "C" __declspec(dllexport) VOID MsgBox(char *szMsg);

    extern "C"表示该函数以C方式导出。

    其实现如下:

    VOID MsgBox(char *szMsg){
        char szModuleName[MAX_PATH]={0};
        GetModuleFileName(NULL,szModuleName,MAX_PATH);
        MessageBox(NULL,szMsg,szModuleName,MB_OK);
    }

    运行函数后弹出一个对话框,显示一个字符串,并显示其所在的进程的进程名。我们分别在DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH下加一个对该函数的调用。

    如下:

    #include <windows.h>
    
    extern "C" __declspec(dllexport) VOID MsgBox(char *szMsg);
    
    BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved){
        switch(ul_reason_for_call){
        case DLL_PROCESS_ATTACH:
            MsgBox("DLL_PROCESS_ATTACH");
            break;
        case DLL_PROCESS_DETACH:
            MsgBox("DLL_PROCESS_DETACH");
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        }
        return TRUE;
    }
    VOID MsgBox(char *szMsg){
        char szModuleName[MAX_PATH]={0};
        GetModuleFileName(NULL,szModuleName,MAX_PATH);
        MessageBox(NULL,szMsg,szModuleName,MB_OK);
    }

    编译该代码,会生成两个好玩的文件:6_10_4.dll和6_10_4.lib。前面是DLL文件,后面是库文件。

    2、静态调用:

    创建一个控制台程序,建立一个cpp文件,添加代码如下:

    #include <windows.h>
    
    extern "C" VOID MsgBox(char *szMsg);
    #pragma comment(lib,"6_10_4")
    
    int main(int argc,char* argv[]){
        MsgBox("hello first dll!");
        return 0;
    }

    对该代码直接编译链接,会报错:无法找到6_10_4.lib文件。把这个文件复制到这个cpp目录下,运行会报错,提示没有找到6_10_4.dll文件。同样,也需要把该文件置于cpp目录下。至此,没有问题了,运行依次弹出三个对话框:

    3、动态调用:

    静态调用就是在编译程序时便把dll信息写入程序里,而动态调用则是在运行时导入dll信息。

    控制台程序cpp代码如下:

    #include <windows.h>
    
    typedef VOID (*PFUNMSG)(char *);
    
    int main(int argc,char* argv[]){
        HMODULE hModule=LoadLibrary("6_10_4.dll");
        if(hModule==NULL){
            MessageBox(NULL,"6_10_4.dll文件不存在","DLL加载失败",MB_OK);
            return -1;
        }
        PFUNMSG pFunMsg=(PFUNMSG)GetProcAddress(hModule,"MsgBox");
        pFunMsg("hello first dll!");
        return 0;
    }

    这里不要求dll文件一定在cpp目录下,在LoadLibrary函数里写入dll的路径即可。运行结果与前面的一样。

    4、其他

    对于未文档化的API,或是没有提供头文件的API,我们可以利用LoadLibrary()和GetProcAddress()这两个API函数来实现对前面那些API的调用。

    LoadLibrary():

    HMODULE LoadLibrary(
        LPCTSTR lpFileName  //file name of module
    );

    该函数只有一个参数,即要加载的DLL文件的路径。

    GetProcAddress():

    GetProcAddress(
        HMODULE hModule,    //handle to DLL module
        LPCSTR  lpProcName  //function name
    );

    该函数有两个参数,hModule是模块的句柄,lpProcName指定要获取函数地址的函数名称。

    另外说下,vc6自带的工具"Depends"挺好用的,可以查看dll程序的导出函数等。它在:菜单“开始”->“程序”->“Microsoft Visual Studio 6.0”->“Microsoft Visual Studio 6.0 Tools”->“Depends”。

  • 相关阅读:
    New version of VS2005 extensions for SharePoint 3.0
    QuickPart : 用户控件包装器 for SharePoint Server 2007
    随想
    发布 SharePoint Server 2007 Starter Page
    如何在SharePoint Server中整合其他应用系统?
    Office SharePoint Server 2007 中文180天评估版到货!
    RMS 1.0 SP2
    SharePoint Server 2007 Web内容管理中的几个关键概念
    如何为已存在的SharePoint站点启用SSL
    Some update information about Office 2007
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4606304.html
Copyright © 2011-2022 走看看