CC++动态连接库DLL编程简易参考示例

    技术2022-05-20  44

    示例一(导出全局函数)

    1.新建空的Dynamic link library 工程myDLL

    在工程内新建两个文件:myDLL.h myDLL.cpp

    各文件源代码:

    myDLLh (指定需要导出的函数、类 )

    /****************************begin**************************/

    extern "C" __declspec( dllexport ) int GetMaxCommDiv(int a,int b);

    extern "C" __declspec( dllexport ) int GetMinCommMul(int a,int b);

    //限定符extern “C”表示以C接口发布函数,用于实现函数的通用性

    /**************************end*****************************/

    myDLL.cpp(各函数、类的实现)

    /****************************begin**************************/

    #include "myDLL2.h"

    int GetMaxCommDiv(int a,int b)// 计算最大公约

    {

        int x=1;

    int ires;   

    if(a<b) return 0;

        if(b==0) return 0;

        while(x!=0) { x=a%b;  a=b; ires=b; b=x;}

        return ires;

    }

     

    int GetMinCommMul(int a,int b)// 计算最小公倍

    {

        int x=1;

        int ires;

    int m,n;

    m=a;n=b;

        if(a<b) return 0;

        if(a==0) return 0;

        if(b==0) return 0;

        while(x!=0) { x=a%b; a=b; ires=b; b=x; }

        ires=(m*n)/(ires);

        return ires;

    }

    /**************************end*****************************/

    编译工程,得到myDLL.dll

    2.新建MFC对话框工程 testDLL

    使用对话框编辑器添加4个编辑框和两个button ,他们的IDC 分别为IDC_EDIT1IDC_EDIT2IDC_EDIT3IDC_EDIT4 IDC_BUTTON1IDC_BUTTON2

    给两个button分别添加映射函数void CTestDLLDlg::OnButton1() {} void CTestDLLDlg::OnButton2() {};函数实现分别如下:

    void CTestDLLDlg::OnButton1() //计算最大公约

    {

           CString str1,str2,strRes;

           int i,j,m;

           typedef int (_cdecl *myType)(int,int);

           GetDlgItem(IDC_EDIT1) ->GetWindowText(str1);

           GetDlgItem(IDC_EDIT2) ->GetWindowText(str2);

           i = atoi(str1); j = atoi(str2);

           HMODULE hModule = ::LoadLibrary("myDLL.dll");//动态加载连接库,得到连接句柄

           myType getValue = (myType)GetProcAddress(hModule,"GetMaxCommDiv");

    //从连接库中获取指定函数的地址

           m = getValue(i,j);

           strRes.Format("%d",m);

           GetDlgItem(IDC_EDIT3)->SetWindowText(strRes);

           FreeLibrary(hModule);//释放连接

    }

    void CTestDLLDlg::OnButton2() //计算最小公倍

    {

           CString str1,str2,strRes;

           int i,j,m;

           typedef int (_cdecl *myType)(int,int);

           GetDlgItem(IDC_EDIT1) ->GetWindowText(str1);

           GetDlgItem(IDC_EDIT2) ->GetWindowText(str2);

           i = atoi(str1); j = atoi(str2);

           HMODULE hModule = ::LoadLibrary("myDLL.dll");

           myType getValue = (myType)GetProcAddress(hModule," GetMinCommMul");

           m = getValue(i,j);

           strRes.Format("%d",m);

           GetDlgItem(IDC_EDIT4)->SetWindowText(strRes);

           FreeLibrary(hModule);

    }

    编译工程,得到testDLL.exe

    3. 将步骤1所得的myDLL.dll复制到testDLL.exe所在目录下,运行testDLL.exe

    示例二(导出C++)

    新建一个dynamic link library 空工程

    DLL头文件myClass.h

    class __declspec(dllexport)myClass

    {

    public:

        int GetMaxCommDiv(int a,int b);//最大公约数

        int GetMinCommMul(int a,int b);//最小公倍数

    };

    DLL实现文件myClass.cpp

    #include "myClass.h"

    int myClass::GetMaxCommDiv(int a,int b) //最大公约数

    {

        return 1;

    }

    //最小公倍数

    int myClass::GetMinCommMul(int a,int b)

    {

           ……

    Return 1;

    }

    新建一个MFC对话框工程testDLL2。使用对话框编辑器添加两个编辑框,两个按钮,它们的IDC分别为:IDC_EDIT1IDC_EDIT2IDC_BUTTON1IDC_BUTTON2,给两个按钮添加映射函数

    testDLL2Dlg.cpp 中加入以下代码; #include "myClass.h"

    #pragma comment(lib,"myClass")

    //隐式(静态)加载连接库,这种方式需要导入库文件(*.lib)随dll文件一同发布,但不需要Windows api 的支持

    ……

    void CTestdll2Dlg::OnButton1()

    {

           CString s;

           myClass myObj;

           s.Format("%d",myObj.GetMaxCommDiv(1,1));

           GetDlgItem(IDC_EDIT1)->SetWindowText(s);

    }

     

    void CTestdll2Dlg::OnButton2()

    {

           CString s;

           myClass myObj;

           s.Format("%d",myObj.GetMinCommMul(1,1));

           GetDlgItem(IDC_EDIT2)->SetWindowText(s);  

    }

    将步骤1myClass.h myClass.lib myClass.dll 复制到当前工程目录下,编译、运行工程 即可测试。

    这种方式加载的类可以像在自己工程内部定义的类一样,而且不需要声明加载DLL,因此这种方式又被称为隐式加载

    可以仅导出类的成员函数,如下所示。

    class (dllexport)myClass

    {

    public:

        int GetMaxCommDiv(int a,int b);

        int __declspec GetMinCommMul(int a,int b);//将仅导出此函数

    };

     

    但这样导出的成员函数只能作为全局函数使用

    DllMain简介:

    DllMaindll的入口函数,如果编写dll时没有指定DllMain,那么系统将会为dll分配一个默认的入口函数,用于指定加载或卸载Dll时执行的动作。DllMain不属于导出函数。

    关于VC++ 程序兼容:

    有使用VC++ 编写的DLL 导出函数采用类似如下的声明与定义:

    extern "C" int __declspec(dllexport) __stdcall functionName(int i);//声明

    int __stdcall functionName(int i){}//定义

    //使用extern "C"修饰函数声明,否则,生成的DLL只能供C++调用; //使用__stdcall修饰函数声明及定义,__stdcallWindows API的函数调用方式; 任何编程语言中使用Win32 API LoadLibrary都可以加载这个DLL

    DLL木马简介:

    DLL木马的实现原理是编程者在DLL中包含木马程序代码,随后在目标主机中选择特定目标进程,以某种方式强行指定该进程调用包含木马程序的DLL,最终达到侵袭目标系统的目的。DLL程序被映射到宿主进程的地址空间中,它能够共享宿主进程的资源,并根据宿主进程在目标主机的级别非法访问相应的系统资源; DLL程序没有独立的进程地址空间,从而可以避免在目标主机中留下"蛛丝马迹",达到隐蔽自身的目的。远程线程插入技术指的是通过在另一个进程中创建远程线程的方法进入那个进程的内存地址空间。将木马程序以DLL的形式实现后,需要使用插入到目标进程中的远程线程将该木马DLL插入到目标进程的地址空间,即利用该线程通过调用Windows API LoadLibrary函数来加载木马DLL,从而实现木马对系统的侵害。

     

    以上节选自:《深入浅出Visual C++动态链接库(Dll)编程》

    Traveler

    2011-2-12


    最新回复(0)