Win32 下动态链接库 (DLL) 机制笔记

来自Jack's Lab
跳转到: 导航, 搜索

目录

1 准备

使用 VC++ 带的命令行编译器 cl 前,需用 "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat" 设置环境变量:

C:\> cd workspace\dll
C:\workspace\dll> "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"



2 DLL 导出简单 C 函数

simple.cc:

#include <stdio.h>

#ifdef __cplusplus    // If used by C++ code, 
extern "C" {          // we need to export the C interface
#endif

__declspec(dllexport) int myPuts(char *lpszMsg)
{
    printf("%s\n", lpszMsg);
    return 1;
}

#ifdef __cplusplus
}
#endif


编译生成 DLL:

 cl /LD /Fesimple.dll simple.cc


选项 /LD 告诉编译器创建 DLL

完了会生成 simple.dll simple.lib



2.1 加载时动态链接测试

#include <windows.h>
int myPuts(char *str);   // a function from a DLL
int main(VOID) 
{ 
    int Ret = 1;
    Ret = myPuts("Using the DLL function, HaHaHaHa, Tutututu\n"); 
    return Ret;
}

以上保存为 load.time.link.c


编译之:

 cl /Feload.time.link.exe load.time.link.c simple.lib


simple.lib 为 simple.dll 对应的 import library,链接时为链接器 link.exe 所需要



2.2 运行时动态加载测试

#include <stdio.h> 
#include <windows.h> 

typedef int (*MYFUNC)(char *); 

VOID main(VOID) 
{ 
    HINSTANCE hinstLib; 
    MYFUNC ProcAdd; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 

    //用 LoadLibrary() 加载 simple.dll
    hinstLib = LoadLibrary(TEXT("simple"));    

    // If the handle is valid, try to get the function address.
    if (hinstLib != NULL) 
    { 
        //用 GetProcAddress() 获取 DLL 中函数地址
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("myPuts"));

        // If the function address is valid, call the function.
        if (NULL != ProcAdd) 
        {
            fRunTimeLinkSuccess = TRUE;
            (ProcAdd) (TEXT("Message via DLL function, HaHaHa, TUTUTUTUTU\n")); 
        }

        // Free the DLL module.
        fFreeResult = FreeLibrary(hinstLib); 
    } 

    if (! fRunTimeLinkSuccess) 
        printf("Load DLL failed\n"); 
}

存为 run.time.link.c,如下命令编译之:

 cl /Ferun.time.link.exe run.time.link.c



3 DLL 中导出C++ 类

与导出 C 风格的函数类似,在定义类时用 __declspec(dllexport):

class __declspec(dllexport) MyCppClass
{
    ......
};


编译时,依然用:

 cl /Fesimple.dll /LD smiple.cc


加载时动态链接,则要在使用前加 __declspec(dllimport) 声明之:

 class __declspec(dllimport) MyCppClass;


如下所示列:

----------
comcat.h:
----------
#ifndef _MY_CMATH_H_
#define _MY_CMATH_H_
#ifdef _CLASS_INDLL_
#define _CLASS_DECL_ __declspec(dllexport)
#else 
#define _CLASS_DECL_ __declspec(dllimport)
#endif
class _CLASS_DECL_ CMath 
{ 
public: 
    int Add(int a,int b); 
    CMath(); 
    ~CMath(){}; 
};
#endif


comcat.cc:

#include "comcat.h"
CMath::CMath()
{
};
int CMath::Add(int a, int b)
{
    return a + b;
}


如下命令生成 DLL:

 cl /LD /Fecomcat.dll /D_CLASS_INDLL_ comcat.cc
  



3.1 加载时动态链接测试

class.load.test.cc

#include "comcat.h"
#include <iostream>
int main()
{
    CMath *cm = new CMath;
    std::cout << "cmath's result:" << cm->Add(5, 8) << std::endl;
    return 0;
}


如下命令编译之:

 cl /Feclass.load.test.exe class.load.test.cc comcat.lib









个人工具
名字空间

变换
操作
导航
工具箱