• c++11实现DLL帮助类


      用过DLL的人都会发现,在C++中调用dll中的函数有点繁琐,调用过程如下:在加载dll后还要定义一个对应的函数指针类型,接着调用GetProcAddress获取函数地址,再转成函数指针,最后调用函数。如果一个dll中有上百个函数,这中繁琐的定义会让人不胜其烦,下面将使用C++新特性中的多参数模版、function和type_traits结合起来山西爱你一个通用的dll帮助类。

    1. win32 dll创建

    1.1 mydll.h

    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif
    
    extern "C" MYDLL_API int Add(int, int);
    extern "C" MYDLL_API float MultParmFun(int, float, char*);

    1.2 mydll.cpp

    #include "stdafx.h"
    #include "mydll.h"
    
    #include <iostream>
    using namespace std;
    
    
    MYDLL_API int Add(int a, int b)
    {
        cout << "entered:" << __FUNCTION__ << endl;
        cout << "参数分别为:" << a << " "<< b << endl;
        return a + b;
    }
    
    MYDLL_API float MultParmFun(int a, float b, char* pBuff)
    {
        cout << "entered:" << __FUNCTION__ << endl;
        cout << "参数分别为:" << a << " " << b << " "<< pBuff<< endl;
        if (!pBuff)
        {
            return .0;
        }
    
        return a * b;
    }

    2. dll导出函数调用一般方法

    #include "stdio.h"
    #include <windows.h>
    #include <string>
    #include <codecvt>
    #include <iostream>
    using namespace std;
    
    string UncodeToAnsi(wstring &wstr)
    {
        wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
        return convert.to_bytes(wstr);
    }
    
    wstring AnsiToUnicode(string &str)
    {
        wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
        return convert.from_bytes(str);
    }
    
    void main()
    {
        HMODULE hMode = LoadLibrary(L"mydll");
        if (!hMode)
        {
            return;
        }
    
        typedef int(*Add)(int, int);
        wstring wstr = L"Add";
        string str = UncodeToAnsi(wstr);
        Add AddFun = (Add)GetProcAddress(hMode, str.c_str());
        cout << AddFun(2, 3) << endl;
    
        typedef float(*MultParm)(int, float, char*);
        wstring wstr1 = L"MultParmFun";
        string str1 = UncodeToAnsi(wstr1);
        MultParm MultParmFun = (MultParm)GetProcAddress(hMode, str1.c_str());
        cout << MultParmFun(2, 3, "helloworld") << endl;
    }

    3. DLL帮助类的实现

    3.1 代码实现

    #pragma once
    
    /*
    DLL函数调用帮助类
    
    实现的关键:
        如何将一个FARPROC变成一个函数指针赋值给function,然后再调用可变参数执行,
        函数的返回值通过std::result<function<T>(ARGS...)>来泛化,使得不同的dll
        函数都可以用相同的方法来调用
    
    需解决以下几个问题:
    1.函数定义
    2.函数调用多参数
    3.返回值
    */
    
    #include<functional>
    #include<string>
    using namespace std;
    
    #include "mydll.h"
    #include <windows.h>
    
    bool InitDllHandle(HMODULE &hModule)
    {
        hModule = LoadLibrary(L"mydll");
        if (!hModule)
        {
            return false;
        }
        return true;
    }
    
    template<typename T>
    function<T> GetFunction(HMODULE &hModule, string &strFunName)
    {
        FARPROC funAddress= (FARPROC)GetProcAddress(hModule, strFunName.c_str());
    
        return function<T>((T*)funAddress);
    }
    
    template<typename T, typename ...ARGS>
    typename result_of<function<T>(ARGS...)>::type ExcecuteFunc(HMODULE &hModule, string &strFunName, ARGS ...args)
    {
        function<T> fun = GetFunction<T>(hModule, strFunName);
        return fun(args...);
    }

    3.2 测试

    #include "stdio.h"
    
    #include "DllHelper.h"
    
    #include <string>
    #include <codecvt>
    #include <iostream>
    using namespace std;
    
    string UncodeToAnsi(wstring &wstr)
    {
        wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
        return convert.to_bytes(wstr);
    }
    
    wstring AnsiToUnicode(string &str)
    {
        wstring_convert<codecvt<wchar_t, char, mbstate_t>> convert(new codecvt<wchar_t, char, mbstate_t>("CHS"));
        return convert.from_bytes(str);
    }
    
    void main()
    {
        HMODULE hMoudle;
        bool bResult = InitDllHandle(hMoudle);
        if (!bResult)
        {
            cout << "句柄为空!" << endl;
        }
        string str = "Add";
        int a = ExcecuteFunc<int(int, int)>(hMoudle, str, 2, 3);
        string str1 = "MultParmFun";
        float b = ExcecuteFunc<float(int,float,char*)>(hMoudle, str1, 2, 3.2, (char *)"helloworld");
    }

  • 相关阅读:
    java类加载过程
    进程和线程
    Java对象的创建
    java异常—检查异常(checked exception)和未检查异常(unchecked exception)
    try...catch...finally语句块
    Mysql数据库索引
    java-生产者消费者模式
    解压字符串
    Java-break,continue,return用法
    归并排序-Java
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9072727.html
Copyright © 2020-2023  润新知