美文网首页
C++11封装Win32 DLL函数装载

C++11封装Win32 DLL函数装载

作者: FredricZhu | 来源:发表于2020-12-23 19:59 被阅读0次

此技术目前基本属于过时状态,除了使用MFC开发有一定作用外,其他基本没有作用。
与Windows平台十分耦合的调用。
技术原理:

  1. 使用std::map缓存装载的函数
  2. 使用变长参数模板获取Win32函数调用
    3.使用std::result_of获取函数返回值
    程序代码如下,
    mydll.h
#ifndef _MY_DLL_H_
#define _MY_DLL_H_
extern "C" __declspec(dllexport) int Add(int &a, int &b);
extern "C" __declspec(dllexport) int Max(const int &a, const int &b);
extern "C" __declspec(dllexport) int Get(const int &a);
#endif

dll_parser.hpp

#ifndef _DLL_PARSER_H_
#define _DLL_PARSER_H_

#include <windows.h>
#include <string>
#include <functional>
#include <map>
#include <iostream>
#include <exception>
using std::cout;
using std::endl;
using std::map;
using std::string;

class DLLParser {
    public:
        DLLParser() {}
        ~DLLParser() {
            Unload();
        }


        bool Load(const string& dllPath) {
            m_hMod = LoadLibrary(LPCTSTR(dllPath.c_str()));

            if(nullptr == m_hMod) {
                cout << "LoadLibrary failed" << endl;
                return false;
            }
            return true;
        }

        template <typename T, typename ... Args>
        typename std::result_of<std::function<T>(Args...)>::type 
        ExecuteFunc(const string& funcName, Args&& ... args) {
            auto f = GetFunction<T>(funcName);
            if(f == nullptr) {
                string s = "Can not find this function " + funcName;
                throw std::logic_error(s); 
            }
            return f(std::forward<Args>(args)...);
        }
    
    private:
        bool Unload() {
            // 说明已经被卸载
            if(m_hMod == nullptr) {
                return true;
            }

            auto b = FreeLibrary(m_hMod);
            // 说明free失败
            if(!b) {
                return false;
            }

            m_hMod = nullptr;
            return true;
        }

        template <typename T> 
        T* GetFunction(const string& funcName) {
            auto funcIt = m_map.find(funcName);
            if(funcIt != m_map.end()) {
                auto func = funcIt->second;
                return (T*)func;
            }

            auto addr = GetProcAddress(m_hMod, funcName.c_str());
            m_map.emplace(funcName, addr);
            return (T*)addr;
        }

    private:
        HMODULE m_hMod;
        map<string, FARPROC> m_map;
};

#endif

main.cpp

#include "dll_parser.hpp"
#include <cstdlib>

void TestDllParser() {
    DLLParser parser;
    string s = "mydll.dll";
    // 加载 dll
    parser.Load(s);

    int a = 5;
    int b = 8;

    auto max = parser.ExecuteFunc<int(const int&, const int&)>("Max", a , b);
    cout << "Max(5, 8): " << max << endl;

    a = 7;
    b = 3;
    max = parser.ExecuteFunc<int(const int&, const int&)>("Max", a, b);
    cout << "Max(7, 3): " << max << endl;

    auto add = parser.ExecuteFunc<int(int&, int&)>("Add", a, b);
    cout << "Add(7, 3): " << add << endl;
}

int main(void) {
    TestDllParser();

    cout << "请按任意键继续..." << endl;
    getchar();
    return 0;
}

Makefile如下,

TAR=main
WORKSPACE_DIR=.
CC:=g++
LIB_PATH =-L.

.PHONY: build clear all

build:
    $(CC) -std=c++11 $(WORKSPACE_DIR)/mydll.h $(WORKSPACE_DIR)/main.cpp -g -o $(TAR) $(LIB_PATH)

all: clear build

clear:
    rm -rf $(TAR)

程序输出如下


图片.png

相关文章

网友评论

      本文标题:C++11封装Win32 DLL函数装载

      本文链接:https://www.haomeiwen.com/subject/oopunktx.html